为了清晰的展示两者之间的关系
我们现在有个需求,运行容器时打印出当前ip地址
那么我们来编写Dockerfile
FROM centos
LABEL maintainer "lbxlh<1318659507@qq.com>"
# curl 工具
RUN yum install -y curl
# 查看IP地址
CMD [ "curl","-s","http://myip.ipip.net/" ]
cmd
注意看我们在Dockerfile文件中添加了一个 curl工具,然后用CMD命令执行当前IP.
构建镜像
╰─ docker build -f Dockerfile -t centos-ip .
[+] Building 10.9s (6/6) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 204B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/centos:latest 0.0s
=> CACHED [1/2] FROM docker.io/library/centos 0.0s
=> [2/2] RUN yum install -y curl 10.5s
=> exporting to image 0.2s
=> => exporting layers 0.2s
=> => writing image sha256:0a29edbad1ce7b74fbd8d745ee5cecc2669a2e44fcab8334bb2dfe5dc4aefc6a 0.0s
=> => naming to docker.io/library/centos-ip
万年叮嘱 别忘了 尾部的 .
运行容器
╰─ docker run --rm centos-ip
当前 IP:118.73.0.214 来自于:中国 山西 临汾 联通
确实按照我们预想的内容输出了,但是如果我想输出协议头咋办。
这时候熟悉curl的小伙伴就要说了,加个 -i 参数不就行了吗。
那么我们试试看
╭─░▒▓ ~/Public/docker-test-volume ▓▒░──────────────────────────────────────────────────────────────────────────────────────────────────░▒▓ ✔ at 18:47:05 ▓▒░
╰─ docker run --rm centos-ip -i
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-i": executable file not found in $PATH: unknown.
我们发现这里的错误是,-i 不是一个有效的命令。
通过查阅官方文档后我们发现:
There can only be one CMD instruction in a Dockerfile. If you list more than one CMD then only the last CMD will take effect.
一个 Dockerfile中,如果有多条CMD命令,那么只会有最后一条生效。
因此我们在编写Dockerfile时要注意这点,如果需要多行命令,那么建议写成脚本,然后用CMD命令去执行。
当我们使用 docker run 命令去执行镜像时,如果我们能附加参数,那么这里的参数就会替代掉我们写的 CMD。
这就是为什么上面 显示 -i 不是有效执行文件。
既然我们发现这个这个问题,那么如何解决呢。
前面知道了,会替换命令,那么我们写个完整的命令不就行了?
╭─░▒▓ ~/Downloads/darwin_amd64 ▓▒░──────────────────────────────────────────────────────────────░▒▓ ✔ at 15:09:19 ▓▒░
╰─ docker run --rm centos-ip curl -s myip.ipip.net -i
HTTP/1.1 200 OK
Date: Tue, 21 Dec 2021 07:09:27 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 68
Connection: keep-alive
X-Via-JSL: fdc330b,-
Set-Cookie: __jsluid_h=121b221c391f3d706dabf95003f1687d; max-age=31536000; path=/; HttpOnly
X-Cache: bypass
当前 IP:118.73.202.27 来自于:中国 山西 临汾 联通
想必到这里已经清楚了CMD命令如何用了吧。
但是如果每次都这样替换,未免有些太过于繁琐,那么有没有一种方案,给我们已经写好的命令中添加参数呢?
entrypoint
entry和cmd是一样的都是在容器运行时执行对应的指令,和cmd不同的是
当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令
那么继续上面的例子,我们来将cmd命令替换成entrypoint
FROM centos
LABEL maintainer "lbxlh<1318659507@qq.com>"
# curl 工具
RUN yum install -y curl
# 查看IP地址
ENTRYPOINT [ "curl","-s","http://myip.ipip.net/" ]
╭─░▒▓ ~/Public/docker-test-volume ▓▒░───────────────────────────────────────────────────────────░▒▓ ✔ at 15:21:14 ▓▒░
╰─ docker run --rm centos-ip
当前 IP:118.73.202.27 来自于:中国 山西 临汾 联通
╭─░▒▓ ~/Public/docker-test-volume ▓▒░───────────────────────────────────────────────────────────░▒▓ ✔ at 15:21:16 ▓▒░
╰─ docker run --rm centos-ip -i
HTTP/1.1 200 OK
Date: Tue, 21 Dec 2021 07:21:20 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 68
Connection: keep-alive
X-Via-JSL: 2633f0d,-
Set-Cookie: __jsluid_h=b4b4e6ee1a68675af8ecb3fee1406613; max-age=31536000; path=/; HttpOnly
X-Cache: bypass
当前 IP:118.73.202.27 来自于:中国 山西 临汾 联通
这样是不是就解决了我们上面的问题呢。
还有一件事:
一个 Dockerfile中,如果有多条ENTRYPOINT命令,那么只会有最后一条生效。