本文一起看下Dockerfile中经常用到的几个类似命令,RUN,CMD,ENTRYPOINT。
想要有容器我们就必须先创建镜像,而想要有镜像,我们则必须写一个用来描述想要创建的镜像的文件,这个文件我们一般叫做Dockerfile(非强制)
,则容器怎么来的就如下图:
经过上图的过程1
我们就有了镜像,经过过程2
我们就有了容器了,知道了这个过程,我们就可以来正式开始分析RUN,CMD,ENTRYPOINT命令了。
RUN命令是在上图过程1中执行的,如下的Dockerfile:
FROM busybox
WORKDIR /var
RUN pwd
则执行docker build时就会输出pwd
的结果:
dongyunqi@dongyunqi-virtual-machine:~$ docker build -t test-push-dockerhub:0.1 -f howPwd.txt helloworld-app/
Sending build context to Docker daemon 8.738kB
Step 1/3 : FROM busybox
---> 827365c7baf1
Step 2/3 : WORKDIR /var
/var # 这里就是pwd的输出,其实输出的就是工作目录,不过输出的到底是什么此时不重要,我们主要是验证pwd在docker build时执行了
Step 3/3 : RUN pwd
---> Using cache
---> 7975c01019bd
Successfully built 7975c01019bd
在容器启动时执行的命令,一般用来启动应用等,如下Dockerfile:
dongyunqi@dongyunqi-virtual-machine:~/test$ cat testEntrypoint.txt
FROM busybox
CMD echo "hello world"
构建:
dongyunqi@dongyunqi-virtual-machine:~/test$ docker build -t test-entrypoint:v0.1 -f testEntrypoint.txt .
...
运行容器:
dongyunqi@dongyunqi-virtual-machine:~/test$ docker run --rm test-entrypoint:v0.1
hello world
可以看到正常输出了。另外如果是有多个CMD只会保留最后一个,如下:
FROM busybox
CMD echo "hello world"
CMD echo "hello world1111"
测试:
dongyunqi@dongyunqi-virtual-machine:~/test$ docker build -t test_entrypoint:v0.1 -f testEntrypoint.txt .
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM busybox
---> 827365c7baf1
Step 2/3 : CMD echo "hello world"
---> Using cache
---> c596d2e7bfb5
Step 3/3 : CMD echo "hello world1111"
---> Running in 9369670af208
Removing intermediate container 9369670af208
---> d7d08688d050
Successfully built d7d08688d050
Successfully tagged test_entrypoint:v0.1
dongyunqi@dongyunqi-virtual-machine:~/test$ docker run --rm test_entrypoint:v0.1
hello world1111
dongyunqi@dongyunqi-virtual-machine:~/test$
可以看到只输出了hello world1111
。以上的是shell格式,我们也可以用Exec 格式,如下:
dongyunqi@dongyunqi-virtual-machine:~/test$ cat testEntrypoint.txt
FROM busybox
CMD ["/bin/echo", "Hello world222"]
测试:
dongyunqi@dongyunqi-virtual-machine:~/test$ docker build -t test_entrypoint:v0.1 -f testEntrypoint.txt .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM busybox
---> 827365c7baf1
Step 2/2 : CMD ["/bin/echo", "Hello world222"]
---> Running in d69c8fdbb1a4
Removing intermediate container d69c8fdbb1a4
---> 5e0920f3e988
Successfully built 5e0920f3e988
Successfully tagged test_entrypoint:v0.1
dongyunqi@dongyunqi-virtual-machine:~/test$ docker run --rm test_entrypoint:v0.1
Hello world222
可以看到正常输出了Hello world222
。但是如果是在docker run时指定了启动命令,则会覆盖CMD,如下:
dongyunqi@dongyunqi-virtual-machine:~/test$ docker run --rm test_entrypoint:v0.1 /bin/echo "hey man!"
hey man!
ENTRYPOINT在Dockerfile中的表现和CMD是一样的,但是ENTRYPOINT不会被docker run中指定的命令覆盖,但是也分为两种情况,如果是使用shell格式的话则docker run中指定的命令将会被忽略,如下:
dongyunqi@dongyunqi-virtual-machine:~/test$ cat testEntrypoint.txt
FROM busybox
ENTRYPOINT echo "Hello world44444"
dongyunqi@dongyunqi-virtual-machine:~/test$ docker build -t test_entrypoint:v0.1 -f testEntrypoint.txt .
Sending build context to Docker daemon 2.048kB
...
dongyunqi@dongyunqi-virtual-machine:~/test$ docker run --rm test_entrypoint:v0.1 11111111111/bin/echo "hey man!"
Hello world44444
如果是Exec格式的话则会被当做参数追加到后面,如下:
dongyunqi@dongyunqi-virtual-machine:~/test$ cat testEntrypoint.txt
FROM busybox
ENTRYPOINT ["echo", "Hello world555"]
dongyunqi@dongyunqi-virtual-machine:~/test$ docker build -t test_entrypoint:v0.1 -f testEntrypoint.txt .
Sending build context to Docker daemon 2.048kB
...
dongyunqi@dongyunqi-virtual-machine:~/test$ docker run --rm test_entrypoint:v0.1 11111111111/bin/echo "hey man!"
Hello world555 11111111111/bin/echo hey man!
相当于是在Dockerfile中写的是ENTRYPOINT ["echo", "Hello world555", "11111111111/bin/echo", "hey man!"]
。
RUN:在docker build生成镜像时执行。
CMD:在docker run时执行,但其会被docker run中指定的命令覆盖
ENTRYPOINT:在docker run时执行,但不会被docker run中指定的命令覆盖,如果是ENTRYPOINT使用shell格式则会忽略,使用Exec格式则会作为参数追加后执行
所以RUN比较独立,CMD和ENTRYPOINT几乎一样,只是在docker run指定指定命令时的表现不同。
参考文章列表:
docker精简入门(五)run&cmd&enterpoint区别 。