我看过许多使用各种语法的Dockerfile。其中一些使用不带方括号的CMD,其中一些使用方括号。根据我的实验,这两个是等效的:

CMD ["/bin/ping", "localhost"]
CMD /bin/ping localhost

但这对于ENTRYPOINT是不正确的。根据我的实验,它们并不相同,只有带括号的版本有效。
ENTRYPOINT ["/docker-entrypoint.sh"]
ENTRYPOINT /docker-entrypoint.sh

我正在实验这些文件:

Dockerfile:
FROM debian:wheezy
COPY docker-entrypoint.sh /
RUN chmod +x /docker-entrypoint.sh

# WORKS AS EXPECTED - FIRST PASS EXECUTION TO /docker-entrypoint.sh THEN TO CMD
ENTRYPOINT ["/docker-entrypoint.sh"]

# PRINTS "PASSED ARGUMENTS" AND EXITS (CMD IS NOT EXECUTED)
# ENTRYPOINT /docker-entrypoint.sh

# WORKS
CMD ["/bin/ping", "localhost"]

# WORKS
# CMD /bin/ping localhost

# ERROR
# CMD "/bin/ping localhost"

docker-entrypoint.sh
#!/bin/bash
echo "PASSED ARGUMENTS"
echo "$@"
exec "$@"

组态:
wakatana@ubuntu:~/df$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.3 LTS
Release:        18.04
Codename:       bionic


wakatana@ubuntu:~/df$ docker info
Client:
 Debug Mode: false

Server:
 Containers: 44
  Running: 8
  Paused: 0
  Stopped: 36
 Images: 98
 Server Version: 19.03.5
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: systemd
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: b34a5c8af56e510852c35414db4c1f4fa6172339
 runc version: 3e425f80a8c931f88e6d94a8c831b9d5aa481657
 init version: fec3683
 Security Options:
  apparmor
  seccomp
   Profile: default
 Kernel Version: 4.15.0-99-generic
 Operating System: Ubuntu 18.04.3 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 3.83GiB
 Name: ubuntu
 ID: GIQ3:BYEM:O3GZ:OWNP:VROK:V3IV:SVMI:MRZ7:CLHG:GDBR:PG3S:6NQU
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Username: xclbr
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

WARNING: No swap limit support


wakatana@ubuntu:~/df$ docker --version
Docker version 19.03.5, build 633a0ea838

我认为最好使用括号版本,但是我想知道为什么甚至允许构建非括号版本?有好处吗?当CMD仅适用于括号版本时,为什么ENTRYPOINT适用于两个版本?

最佳答案

有两个规则:

  • 如果使用JSON数组(“括号”)版本,则它是构成命令的“单词”的显式列表。如果使用裸字符串,则将其包装在/bin/sh -c '...'中。
  • 应用第一条规则后,ENTRYPOINTCMDcombined into a single command

  • 还有一个细节:如果您调用 /bin/sh -c 'command' ,剩下的所有参数将成为位置参数$0$1等,以扩展command字符串;它们不会进一步作为参数传递给command

    因此,如果您的Dockerfile说
    ENTRYPOINT ["/entrypoint.sh"]
    CMD ["/command.sh"]
    

    然后当Docker启动容器时,它们将合并为一个命令行
    /entrypoint.sh /command.sh
    

    但是如果您使用字符串形式
    ENTRYPOINT /entrypoint.sh
    CMD /command.sh
    

    你会得到
    /bin/sh -c '/entrypoint.sh' /bin/sh -c '/command.sh'
    

    它计算字符串/entrypoint.sh并按原样执行它,不带参数;命令丢失。

    通常,您希望允许命令部分成为标准的shell命令(docker run --rm -it some-image /bin/sh对于调试非常有用)。为此,ENTRYPOINT必须为JSON数组形式,并且需要确保运行在其参数中传递的命令(在shell脚本中,以exec "$@"结尾)。

    关于docker - CMD和ENTRYPOINT支架与非支架版本,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/62206384/

    10-16 16:33