207

I use a third party GUI (Synology Docker package) to setup a docker container. However, its limitation makes me need to run the container from the command line. (I want to map another host ip to bind the port)

Now, since there are lots of settings that already done, I would like to retrieve the original run command that start this container, then I can change the port mapping port to new one. eg. "docker run -p 80:8080 gitlab"

I can't find the way to do so, event use "docker inspect", no such information provided.

Please provide some advice to solve this problem.

danronmoon
  • 3,814
  • 5
  • 34
  • 56
Jack Yu
  • 2,350
  • 2
  • 15
  • 15

13 Answers13

233

So how to reverse engineering docker run command?

There is a github repository which try to reverse engineering docker run command, but it is not perfect currently, version is 0.1.2. You should follow it for updating. Maybe one day you can use it to get correct run command with it.

$ sudo pip install runlike

# run the ubuntu image
$ docker run -ti ubuntu bash

$ docker ps -a  
# suppose you get the container ID 1dfff2ba0226

# Run runlike to get the docker run command. 
$ runlike 1dfff2ba0226
docker run --name=elated_cray -t ubuntu bash

Github repository: runlike

Updates:

Run without installing (Thanks @tilo)

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro \
    assaflavie/runlike YOUR-CONTAINER

or set alias and put it in your shell's profile

alias runlike="docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro assaflavie/runlike"

docker ps

runlike YOUR-CONTAINER
BMW
  • 42,880
  • 12
  • 99
  • 116
119

A simpler (?) alternative is to run this docker inspect template, which uses the builtin Go templating capabilities to output a docker run compatible command. The template only covers the most usual command-line options, but it can easily be extended.

This solution has no dependencies on other tools, except docker itself.

docker inspect \
  --format "$(curl -s https://gist.githubusercontent.com/efrecon/8ce9c75d518b6eb863f667442d7bc679/raw/run.tpl)" \
  name_or_id_of_your_running_container
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Emmanuel Frécon
  • 1,201
  • 1
  • 8
  • 5
  • 7
    This answer needs more upvotes, this really is the best solution ! – Joao Costa Aug 17 '21 at 09:09
  • Great answer. To be fair: It is around 4 years younger than the ones with more upvotes :) I really like, that it works without any external depedency! – KingCrunch Mar 15 '22 at 21:15
  • How do I run this in Windows, i.e. Docker Desktop? – ontherocks Nov 04 '22 at 16:52
  • Actually the template has been forked and updated to support the `--mount` options. See here: https://gist.github.com/efrecon/8ce9c75d518b6eb863f667442d7bc679?permalink_comment_id=4462250#gistcomment-4462250 - Updating answer to include it. – Xavi Montero Apr 05 '23 at 14:24
  • 1
    @ontherocks Depends. If you are using WSL for the docker engine for instance, then open the WSL terminal where you could type `docker ps -a` for example. If you are not usgin WSL, then I'd suggest to install git bash https://gitforwindows.org/ which comes with a nice bash for windows. You can do docker commands there connecting to the same engine than Docker Desktop is connecting to. – Xavi Montero Apr 05 '23 at 14:29
  • I am upvoting too. Helped me to properly (e.g. with right parameters) restart a Jupyter container on Google Cloud. – Maciej Skorski Apr 24 '23 at 15:18
  • Template parsing error: template: :22:15: executing "" at <.Mounts>: map has no entry for key "Mounts" – CS QGB May 16 '23 at 15:03
  • Running a some not known script from internet locally is not good idea! Here is a better solution: https://stackoverflow.com/a/47240342/4632019 – Eugen Konkov Jul 19 '23 at 16:14
66

Use docker inspect:

$ docker inspect foo/bar
[
    {
        # …
        "Config": {
            # …
            "Cmd": [
                "/usr/local/bin/script.sh"
            ],
            # …
        }
    }
]

You can programatically parse this with jq:

$ docker inspect foo/bar | jq -r '.[0]["Config"]["Cmd"][0]'
/usr/local/bin/script.sh
Chris Lamb
  • 1,668
  • 15
  • 11
  • 3
    yes I prefer jq too, a slight tweak on the command (a bit easier to type and read IMHO) is: `docker inspect | jq ".[0].Config.Cmd"` – Paul Carroll Jan 14 '19 at 03:19
  • 3
    `"Cmd": null,` Maybe this only works if the container was not started automatically be the docker daemon? – Michael Aug 05 '19 at 10:23
  • 31
    This shows the CMD launched at container start. Definitely not what was asked. – nvidot Jan 13 '21 at 14:57
40

I wrote a simple Node-based CLI tool to generate a docker run command from an existing container.

https://www.npmjs.com/package/rekcod

Here's an example:

$ npm i -g rekcod
$ rekcod redis_container

docker run -d --name redis_container --restart always -h a44159e148e1 \
--expose 6379/tcp -e PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
-e REDIS_VERSION=3.0.7 -e REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-3.0.7.tar.gz \
-e REDIS_DOWNLOAD_SHA1=e56b4b7e033ae8dbf311f9191cf6fdf3ae974d1c \
--entrypoint "/entrypoint.sh" redis "redis-server"

Also handles links and mounted volumes and other stuff.

Not super robust at the moment, but handles more than some of the other things mentioned, and it was more of what I was looking for.

EDIT: In a single command, without installing any software:

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nexdrew/rekcod redis_container
Zagrev
  • 2,000
  • 11
  • 8
superEb
  • 5,613
  • 35
  • 38
  • Nice tool. Another alternative (in Python) is [runlike](https://github.com/lavie/runlike/). (I prefer NodeJS myself though, assuming feature parity) – Venryx Aug 29 '21 at 00:23
  • I know its against policy to say thanks or +1 but fk that, you sir are a gentleman and a scholar and you saved me several hours of copy pasting with your beautiful tool – JSelser Mar 29 '23 at 19:59
9

Use following command to get the arguments for all containers:

docker inspect -f "{{.Name}} {{.Path}} {{.Args}}" $(docker ps -a -q)
Nae
  • 14,209
  • 7
  • 52
  • 79
Abhishek Jain
  • 3,815
  • 2
  • 26
  • 26
  • 6
    This lists the command and arguments for whats running _inside_ container, not how the container was started (i.e. answer to the question you posted the runlike answer 4 minutes after this! :) ). – OzgurH Apr 24 '19 at 10:43
5

Currently it seems we have to go 'docker inspect ' and then manually recreate the run command.

I have found someone attempting to write a bash script to do this: https://gist.github.com/miracle2k/c85b7b077fdb8d54bc89

but it is incomplete and depends on jq.

Rene Wooller
  • 1,107
  • 13
  • 22
5

If you do not want to install anything into your current running Docker server setup, you can simply execute (replace $CONTAINER_NAME with the container name you want to have the run arguments):

docker run -it --rm --volume /var/run/docker.sock:/var/run/docker.sock --privileged docker sh -c "apk add --no-cache nodejs nodejs-npm && npm i -g rekcod && rekcod $CONTAINER_NAME"

(for the rekcod method)

or

docker run -it --rm --volume /var/run/docker.sock:/var/run/docker.sock --privileged docker sh -c "apk add --no-cache py-pip && pip install runlike && runlike $CONTAINER_NAME"

(for the runlike method)

Anthony O.
  • 22,041
  • 18
  • 107
  • 163
3

What could be a simpler (robust) option would be to use something like bash-preexec to capture commands that start with "docker run". You could then store these commands somewhere and retrieve them later.

For example, you could add something like this in your bash profile:

[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh
docker_run_history=~/.docker_run_history
docker_clear_history(){
    echo -n > $docker_run_history
}
docker_search_history(){
    search_for="$@"
    [[ -z $search_for ]] && search_for=".*"
    \cat $docker_run_history | grep "$search_for" | tail -1
}
docker_ps_mod(){
    for c in $(docker ps --format "{{.Image}}"); do 
        echo "Container $c was run using:"
        echo -e "\t$(docker_search_history $c)"
    done
}
docker_hook(){
    if [[ $@ =~ ^"docker run".*$ ]]; then
        \echo "$@" >> $docker_run_history 
    fi
}
preexec(){ 
    docker_hook $@
}

Then you could just run your things:

source ~/.bash_profile
docker run -it --rm -v $(pwd)/data:/data -p 8080:80 image
docker run -d daemon
docker_ps_mod

Which outputs:

Container image was run using:
    docker run -it --rm -v $(pwd)/data:/data -p 8080:80 image
Container daemon was run using:
    docker run -d daemon
cglacet
  • 8,873
  • 4
  • 45
  • 60
  • Interesting alternative. +1 – VonC Jun 19 '17 at 09:05
  • 1
    It is absurd that docker does not record commands history and have a simply piping like this. – Macindows Mar 16 '20 at 07:06
  • Interesting. But using the 'image' name seems a bit weird since multiple container might use the same image. It might be possible to use the value returned from the `docker run ...` command to get back the name of the container? – nvidot Jan 13 '21 at 17:42
2

That docker run command isn't specified in the Dockerfile or any other docker-related documents.

Either you find an example in the documentation associated to your container, or you can infer that docker run with (at least for the command and port mapping) a docker ps -a (but that won't give you the possible --volumes-from options)

Check also /usr/syno/etc/packages/Docker-GitLab/config

This differ from the gitlab config itself, which on Synology is available in /usr/syno/etc/packages/Docker/synology_gitlab.config

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Thanks for mention the config file location of Synology Docker. But the config can't help much more. It's content is much the same as you export a container from Web UI. – Jack Yu Sep 27 '15 at 07:50
1

To reverse the docker run command there is also the following npm package.

https://github.com/nexdrew/rekcod

finrod
  • 521
  • 8
  • 21
1

As noted by @Chris_Lamb, you can use docker inspect to see this and much more. Here is how to load this info to a python dictionary:

import subprocess,json
im_inspect = subprocess.check_output(["docker", "image", "inspect", "datalab-nginx-ui"])
# print(im_inspect.decode("utf-8") ) #if you want to print it
d_inspect = json.loads(im_inspect)
d_inspect
d_inspect[-1]['ContainerConfig']['Cmd']

Example run: enter image description here

ntg
  • 12,950
  • 7
  • 74
  • 95
1

Curious how most answers rely on third parties for that while everything is in the docker inspect JSON. There’s even no need for jq since docker has a JSON formatting option.

Use

docker inspect  -f 'docker run --name {{.Name}} -v {{join .HostConfig.Binds " "}} -p {{.HostConfig.PortBindings}} {{.Config.Image}} {{join .Config.Cmd " "}}' my-osrm-image

E.g. for the actual bash command

docker run -t -i --name my-osrm-image -v "/custom/path/to/data-osrm:/data" -p 80:5000 osrm/osrm-backend osrm-routed --algorithm mld /data/europe-latest.osrm

the above docker inspect command will output

 docker run --name /my-osrm-image -v /custom/path/to/data-osrm:/data -p map[5000/tcp:[{ 80}]] osrm/osrm-backend osrm-routed --algorithm mld /data/europe-latest.osrm

It requires a bit of cleaning but everything is there, and it can be extended to include further options accordingly with the docker inspect JSON output. See also this documentation for the output formatting.

Skippy le Grand Gourou
  • 6,976
  • 4
  • 60
  • 76
0

All docker files are here you can find cmd and mounts for example ls -la /proc/1 just cat it

cat /proc/1/cmdline
nginx: master process nginx -g daemon off;