Create compose file for container started without compose

I have been creating containers manually from the command line for years, but would like to switch to using compose files. What is the simplest way to create correct compose yaml files? I gather that I I can use docker inspect <container ID> and then edit the output, but that generates a very long file. Can I instead derive from my normal command line content what the compose file should look like, and the system will set up much of the other configurations that appear in the inspect output?

I create all of mine right in Container Station when setting up the application…

Hi @beneix

You’re right that docker inspect output is too verbose to convert directly — most of it is runtime state and image defaults that don’t belong in a compose file. Instead of editing the full JSON, we’d suggest extracting only the fields a compose file actually needs, using --format:

C=<container_name>

docker inspect -f '{{.Config.Image}}' $C
docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' $C
docker inspect -f '{{range .Config.Env}}{{println .}}{{end}}' $C
docker inspect -f '{{range $p,$b := .NetworkSettings.Ports}}{{if $b}}{{(index $b 0).HostPort}}:{{$p}}{{println}}{{end}}{{end}}' $C
docker inspect -f '{{range .Mounts}}{{.Source}}:{{.Destination}}{{if not .RW}}:ro{{end}}{{println}}{{end}}' $C
docker inspect -f '{{range $n,$_ := .NetworkSettings.Networks}}{{println $n}}{{end}}' $C

These map directly to the image:, restart:, environment:, ports:, volumes:, and networks: sections of a compose file:

services:
  myapp:
    image: <from command 1>
    container_name: myapp
    restart: <from command 2>
    environment:
      - VAR=value        # from command 3
    ports:
      - "8080:80"        # from command 4
    volumes:
      - /share/Container/myapp:/config   # from command 5

A few tips to keep the file clean:

  1. Environment variables: command 3 lists all env vars, including the image’s built-in defaults (PATH, LANG, etc.). Only copy the ones you set yourself. You can check the image defaults with docker inspect -f '{{range .Config.Env}}{{println .}}{{end}}' <image> and skip anything that appears in both.

  2. Command/entrypoint: don’t add command: or entrypoint: unless you overrode them when creating the container. If docker inspect shows a long startup command, it’s almost always the image’s built-in default — leave it out and the image will handle it.

  3. If the docker CLI isn’t in your PATH over SSH, you can locate it with:

    export PATH="$PATH:$(getcfg container-station Install_Path -f /etc/config/qpkg.conf)/bin"
    
  4. Validate the result with docker compose config before deploying, then bring it up under a new name and compare against the original container before removing it.

Since you mentioned you still have your original docker run commands — that’s actually the ideal source. A compose file is essentially a YAML representation of those same flags (-p → ports, -v → volumes, -e → environment, --restart → restart), so translating your own commands gives you a cleaner file than reverse-engineering a running container.

Going forward, you can also create applications directly as compose files in Container Station (Applications → Create), which gives you a YAML editor with validation built in — as NA9D showed above.