如何显示Docker容器的运行命令。

213
我使用第三方GUI(Synology Docker包)来设置一个Docker容器。然而,由于其限制,我需要从命令行运行该容器。(我想将另一个主机IP映射到绑定的端口)
现在,由于已经进行了很多设置,我希望能够检索启动此容器的原始运行命令,然后我可以将端口映射端口更改为新的端口。例如 "docker run -p 80:8080 gitlab"
我找不到这样做的方法,即使使用"docker inspect",也没有提供这样的信息。
请提供一些建议来解决这个问题。

13
@capitalistpug 那个问题恰好与这个相反 - 它是关于容器内部的命令,而这个是关于用于启动容器的命令。 - Niels Keurentjes
2
历史 | grep 'docker run' - Adrian May
7
Docker 没有内置此选项,这真是令人惊讶。 - Macindows
@AdrianMay 啊,没错,POSIX来拯救了。 - mtyson
13个回答

238

那么如何逆向工程Docker运行命令呢?

有一个github仓库试图逆向工程Docker运行命令,但目前它并不完美,版本为0.1.2。你应该随时关注更新。也许有一天你可以使用它来获取正确的运行命令。

$ 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代码库:runlike

更新:

不需安装即可运行(感谢@tilo)

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

或者设置别名并将其放入您的shell配置文件中。
alias runlike="docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro assaflavie/runlike"

docker ps

runlike YOUR-CONTAINER

2
在Synology DSM上设置runlike有点困难,但我会尝试的。谢谢! - Jack Yu
1
我必须使用sudo pip install runlike。 - Simon
38
运行命令如下:docker run -v /var/run/docker.sock:/var/run/docker.sock \ assaflavie/runlike YOUR-CONTAINER - Tilo
1
谢谢@Tilo。在我的Synology NAS上完美运行。 - marcelbrueckner
5
出于安全考虑,将docker.sock以只读方式挂载会更好,例如:alias runlike="docker run --rm -v/var/run/docker.sock:/var/run/docker.sock:ro assaflavie/runlike" - Joao Costa
显示剩余5条评论

131
一个更简单的选择是运行this docker inspect template,它使用内置的Go模板功能来输出一个docker run兼容命令。该模板仅涵盖最常见的命令行选项,但可以轻松扩展。
这个解决方案除了Docker本身之外没有其他工具的依赖。
docker inspect \
  --format "$(curl -s https://gist.githubusercontent.com/efrecon/8ce9c75d518b6eb863f667442d7bc679/raw/run.tpl)" \
  name_or_id_of_your_running_container

7
这个回答需要更多的赞,这确实是最好的解决方案! - Joao Costa
很棒的答案。公正地说:它比得到更多赞的那些回答年轻了约4年 :) 我真的很喜欢它可以在没有任何外部依赖的情况下工作! - KingCrunch
我该如何在Windows上运行它,即Docker桌面版? - ontherocks
1
@ontherocks 这要看情况。例如,如果您正在使用WSL作为docker引擎,则可以打开WSL终端,然后输入“docker ps -a”等命令。如果您没有使用WSL,则建议安装git bash https://gitforwindows.org/,它带有一个很好的Windows bash。您可以在那里执行docker命令,连接到与Docker Desktop相同的引擎。 - Xavi Montero
在本地运行一个未知的来自互联网的脚本不是个好主意!这里有一个更好的解决方案:https://dev59.com/_FwY5IYBdhLWcg3wU2XA#47240342 - Eugen Konkov
显示剩余3条评论

66

使用docker inspect命令:

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

你可以使用jq进行编程解析:

$ docker inspect foo/bar | jq -r '.[0]["Config"]["Cmd"][0]'
/usr/local/bin/script.sh

3
是的,我也更喜欢 jq,命令略微调整一下(在我看来更容易输入和阅读):docker inspect <CONTAINER> | jq ".[0].Config.Cmd" - Paul Carroll
3
"Cmd": null, 这可能只在容器没有被 Docker 守护进程自动启动的情况下才有效? - Michael
33
这显示了容器启动时启动的 CMD。绝对不是所要求的内容。 - nvidot

40

我写了一个简单的基于Node的CLI工具,可以从现有容器生成一个docker run命令。

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

这里是一个例子:

$ 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"

还处理链接、挂载卷和其他内容。

目前并不是非常健壮,但比其他提到的一些东西更好处理,而且正是我在寻找的。

编辑: 在不安装任何软件的情况下,使用单个命令:

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nexdrew/rekcod redis_container

不错的工具。另一个选择(使用Python)是runlike。(虽然我更喜欢NodeJS,假设功能相当的话) - Venryx
我知道说谢谢或+1是违反政策的,但是该死的,您先生是一位绅士和学者,您的美妙工具为我节省了数小时的复制粘贴时间。 - JSelser

10
使用以下命令获取所有容器的参数:
docker inspect -f "{{.Name}} {{.Path}} {{.Args}}" $(docker ps -a -q)

6
这里列出了容器内运行的命令和参数,而不是容器启动的方式(即回答你在此之后4分钟发布的问题“runlike answer”的答案! :))。 - OzgurH

6

如果您不想在当前正在运行的Docker服务器设置中安装任何内容,您可以简单地执行以下操作(将$CONTAINER_NAME替换为您想要运行参数的容器名称):

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"

(针对 rekcod 方法)
或者
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"

(针对runlike方法)

我认为-it--rm之间应该有一个空格。 - IpsRich
@IpsRich 您是正确的,我已经修改了我的答案,谢谢! - Anthony O.

5

目前看来,我们必须执行 'docker inspect' 命令,然后手动重新创建运行命令。

我发现有人试图编写一个 bash 脚本来实现这个功能: https://gist.github.com/miracle2k/c85b7b077fdb8d54bc89

但它是不完整的,并且依赖于 jq 工具。


3
可能更简便(稳健)的选项是使用类似于 bash-preexec 的工具来捕获以 "docker run" 开头的命令。然后,您可以将这些命令存储在某个地方并稍后检索它们。
例如,您可以在 bash 配置文件中添加以下内容:
[[ -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 $@
}

那么你只需要运行你的东西:
source ~/.bash_profile
docker run -it --rm -v $(pwd)/data:/data -p 8080:80 image
docker run -d daemon
docker_ps_mod

这会输出:

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

有趣的替代方案。+1 - VonC
1
Docker 不记录命令历史,也没有像这样简单的管道操作,这太荒谬了。 - Macindows
有趣。但是使用“image”名称似乎有点奇怪,因为多个容器可能使用相同的镜像。也许可以使用从docker run ...命令返回的值来获取容器的名称? - nvidot

3

好奇大多数答案都依赖第三方,而所有内容都在docker inspect JSON中。甚至不需要jq,因为docker有一个JSON格式选项。

使用

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

例如实际的bash命令

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

上述docker inspect命令将输出

 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

需要进行一些清理,但所有内容都在那里,并且可以根据 docker inspect 的 JSON 输出进一步扩展以包括其他选项。有关输出格式,请参见此文档


2
那个docker run命令没有在Dockerfile或其他与docker相关的文档中指定。
你可以在与容器相关联的文档中找到示例,或者可以推断出使用docker run(至少对于命令和端口映射)以及docker ps -a(但这不会给出可能的--volumes-from选项)
还要检查/usr/syno/etc/packages/Docker-GitLab/config 这与Synology上的gitlab配置不同,在那里可以在/usr/syno/etc/packages/Docker/synology_gitlab.config中找到。

感谢提到Synology Docker的配置文件位置。但是配置文件并不能提供太多帮助。它的内容与从Web UI导出容器的内容基本相同。 - Jack Yu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接