Docker容器的安装配置,以及 Dockerfile 的使用方法
Docker简介Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器或Windows 机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。相对于传统的虚拟机省去了虚拟化和虚拟操作系统,极大的节约了资源。它会共享宿主机的操作系统。而且虚拟机必须要kvm的支持才可以启用。一个完整的Docker有以下几
Docker简介
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器或Windows 机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。
相对于传统的虚拟机省去了虚拟化和虚拟操作系统,极大的节约了资源。它会共享宿主机的操作系统。
而且虚拟机必须要kvm的支持才可以启用。
一个完整的Docker有以下几个部分组成:
- DockerClient客户端
- Docker Daemon守护进程
- Docker Image镜像
- DockerContainer容器 [2]
docker的体积非常小,最多不超过几百M,相对于十几个G的虚拟机来说太小了,一台主机可以同时存在上千个docker,而且他们是彼此安全隔离的互不影响,他们就相当于在系统中运行的程序。
局限
Docker并不是全能的,设计之初也不是KVM之类虚拟化手段的替代品,简单总结几点:
- Docker是基于Linux 64bit的,无法在32bit的linux/Windows/unix环境下使用
- LXC是基于cgroup等linux kernel功能的,因此container的guest系统只能是linux base的
- 隔离性相比KVM之类的虚拟化方案还是有些欠缺,所有container公用一部分的运行库
- 网络管理相对简单,主要是基于namespace隔离
- cgroup的cpu和cpuset提供的cpu功能相比KVM的等虚拟化方案相比难以度量(所以dotcloud主要是按内存收费)
- Docker对disk的管理比较有限
- container随着用户进程的停止而销毁,container中的log等用户数据不便收集
安装
[root@server1 docker]# yum install docker-ce-18.09.6-3.el7.x86_64.rpm \
docker-ce-cli-18.09.6-3.el7.x86_64.rpm \
containerd.io-1.2.5-3.1.el7.x86_64.rpm \
container-selinux-2.21-1.el7.noarch.rpm -y
[root@server1 docker]# systemctl enable --now docker
配置
我们现在导入一个景象:
[root@server1 docker]# docker load -i game2048.tar # 导入
011b303988d2: Loading layer [==================================================>] 5.05MB/5.05MB
36e9226e74f8: Loading layer [==================================================>] 51.46MB/51.46MB
192e9fad2abc: Loading layer [==================================================>] 3.584kB/3.584kB
6d7504772167: Loading layer [==================================================>] 4.608kB/4.608kB
88fca8ae768a: Loading layer [==================================================>] 629.8kB/629.8kB
Loaded image: game2048:latest
[root@server1 docker]# docker run -d --name game1 -p 80:80 game2048 ##运行容器
7775c61ecf1a06832c67b70bf7a6b011dbf839ad6c730a1c1403f45f10059895
## 运行, -d后台运行,--name容器名 -p端口映射,由于安全隔离的原因,先访问物理机80端口,在访问server1的80端口
[root@server1 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
game2048 latest 19299002fdbe 3 years ago 55.5MB
[root@server1 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7775c61ecf1a game2048 "/bin/sh -c 'sed -i …" 12 seconds ago Up 11 seconds 0.0.0.0:80->80/tcp, 443/tcp game1
# 就运行起来了
容器退出后可以用docker ps -a 查看。
我们现在在浏览器访问
就可以访问了,这个2048的游戏镜像就打包到容器中去了。
[root@server1 docker]# du -sh game2048.tar
55M game2048.tar ##它只有55M的大小
[root@server1 docker]# docker info 查看docker信息
Containers: 1
Running: 1
Paused: 0
Stopped: 0
Images: 1
Server Version: 18.09.6
...
Swarm: inactive ## swarm是docker的管理引擎,目前k8s比较流行
Runtimes: runc
...
Docker Root Dir: /var/lib/docker ## 工作目录
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
Product License: Community Engine
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
## 这里有两个警告,我们处理一下
[root@server1 docker]# vim /etc/sysctl.d/docker.conf
[root@server1 docker]# sysctl --system 让其生效
最后的警告就没有了。
docker的数据都存放在 /var/lib/docker 下
[root@server1 docker]# ll
total 4
drwx------ 2 root root 24 May 23 09:58 builder
drwx------ 4 root root 92 May 23 09:58 buildkit
drwx------ 3 root root 78 May 23 10:01 containers 容器
drwx------ 3 root root 22 May 23 09:58 image 镜像
drwxr-x--- 3 root root 19 May 23 09:58 network
drwx------ 10 root root 4096 May 23 10:01 overlay2 引擎
drwx------ 4 root root 32 May 23 09:58 plugins 插件
drwx------ 2 root root 6 May 23 09:58 runtimes
drwx------ 2 root root 6 May 23 09:58 swarm
drwx------ 2 root root 6 May 23 10:00 tmp
drwx------ 2 root root 6 May 23 09:58 trust
drwx------ 2 root root 25 May 23 09:58 volumes 数据存放目录
我们在运行一个容器:
运行一个ubuntu的系统镜像。
[root@server1 docker]# docker load -i ubuntu.tar
56abdd66ba31: Loading layer [==================================================>] 196.8MB/196.8MB
9468150a390c: Loading layer [==================================================>] 208.9kB/208.9kB
11083b444c90: Loading layer [==================================================>] 4.608kB/4.608kB
5f70bf18a086: Loading layer [==================================================>] 1.024kB/1.024kB
Loaded image: ubuntu:latest
[root@server1 docker]# du -sh ubuntu.tar
188M ubuntu.tar
[root@server1 docker]# docker run -it --name vm1 ubuntu ## -it以交互的方式访问容器
root@6c10eb92f7a4:/#
root@6c10eb92f7a4:/# 这里我们就得到了ubuntu的系统
root@6c10eb92f7a4:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@6c10eb92f7a4:/# uname -r
3.10.0-957.el7.x86_64
它的内核版本和server1的内核一样,说明它是寄宿于server1的系统之上的
root@6c10eb92f7a4:/# touch file1
root@6c10eb92f7a4:/# touch file2 ## 创建两个文件,之后退出
root@6c10eb92f7a4:/# exit
exit
[root@server1 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7775c61ecf1a game2048 "/bin/sh -c 'sed -i …" 41 minutes ago Up 41 minutes 0.0.0.0:80->80/tcp, 443/tcp game1
[root@server1 docker]# docker ps -a 加上-a参数可以看到退出的同期
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6c10eb92f7a4 ubuntu "/bin/bash" 4 minutes ago Exited (0) 18 seconds ago vm1
7775c61ecf1a game2048 "/bin/sh -c 'sed -i …" 41 minutes ago Up 41 minutes 0.0.0.0:80->80/tcp, 443/tcp game1
[root@server1 docker]# docker rm vm1
vm1
[root@server1 docker]# docker run -it --name vm1 ubuntu
root@b1908317d127:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
重新运行之后发现之前创建的文件不见了。
这就证明容器就类似于我们的快照,可以随时还原,但是每一次退出都不能保存我们的操作的话,容器就失去了意义.
docker创建容器和创建快照都使用的是qcow的机制。
- q --> qemu-kvm 虚拟化
- cow --> copy on write 写时复制
[root@server1 docker]# docker history game2048:latest
IMAGE CREATED CREATED BY SIZE COMMENT
19299002fdbe 3 years ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "sed … 0B
<missing> 3 years ago /bin/sh -c #(nop) EXPOSE 80/tcp 0B
<missing> 3 years ago /bin/sh -c #(nop) COPY dir:cb74e9c037a3d501c… 600kB
<missing> 3 years ago /bin/sh -c #(nop) MAINTAINER Golfen Guo <go… 0B
<missing> 3 years ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
<missing> 3 years ago /bin/sh -c #(nop) EXPOSE 443/tcp 80/tcp 0B
<missing> 3 years ago /bin/sh -c #(nop) COPY file:d15ceb73c6ea776c… 1.1kB
<missing> 3 years ago /bin/sh -c #(nop) COPY file:af94db45bb7e4b8f… 643B
<missing> 3 years ago /bin/sh -c GPG_KEYS=B0F4253373F8F6F510D42178… 50.1MB
<missing> 3 years ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.11.7 0B
<missing> 3 years ago /bin/sh -c #(nop) MAINTAINER NGINX Docker M… 0B
<missing> 3 years ago /bin/sh -c #(nop) ADD file:7afbc23fda8b0b387… 4.8MB
- 这里我们可以看到的是镜像层,记录了这个镜像生产的全过程,这个部分是封装好, 是不可以在进行改动的,如果我们想要保存我们的更改,就要使用 cow 的机制,对容器层进行更改。
- 就是我们更改完成后将其保存成一个新的容器,这样的话才可以保存我们的更改。而不能保存在本层中。因为本层是只读的,就像系统快照,它只有几百k,但是我们我可以看到系统的全部内容,它就是把新的更改和能看到的内容打包到一个容器里面,这就是cow的机制。
新镜像的构建
[root@server1 docker]# docker rm -f vm1
vm1
[root@server1 docker]# docker rm -f game1
game1
镜像的构建有两种方式,第一种是:
dicker commit
我们获取一个busybox的镜像,它是一个linux基础的文件系统,它只有一些基础的命令和文件。
containerd.io-1.2.5-3.1.el7.x86_64.rpm distroless.tar docker-ce-cli-18.09.6-3.el7.x86_64.rpm nginx.tar ubuntu.tar
[root@server1 docker]# docker load -i busybox.tar ## 加载
8a788232037e: Loading layer [==================================================>] 1.37MB/1.37MB
Loaded image: busybox:latest
[root@server1 docker]# du -sh busybox.tar
1.4M busybox.tar
[root@server1 docker]# docker run -it --name vm1 busybox
/ # ls
bin dev etc home proc root sys tmp usr var ## 只有一些基础的目录
/ # vi testfile ## 编辑一个文件
直接exit的话就直接关闭容器了,那么我们想退出容器,并暂时保留运行状态的话,按 CTRL + P + Q
/ # vi testfile
/ # [root@server1 docker]# docker ps ## 可以看出 vm1 还在运行
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
47c17a5d6d5a busybox "sh" 4 minutes ago Up 4 minutes vm1
[root@server1 docker]# docker attach vm1 # 使用这个命令重新连接
/ # ls
bin dev etc home proc root sys testfile tmp usr var
/ # read escape sequence
[root@server1 docker]#
那末这时我们如果想要保存这份更改的话,就要打包成一个新的镜像才可以:
[root@server1 docker]# docker commit vm1 test:v1 # 提交,test是镜像名,v1是标签
sha256:ccbb07c70420075c8e33dd47859616658344cfd0fd91cae92adff74d209985df
[root@server1 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test v1 ccbb07c70420 5 seconds ago 1.15MB 这就是新生成的镜像
busybox latest 59788edf1f3e 19 months ago 1.15MB
game2048 latest 19299002fdbe 3 years ago 55.5MB
ubuntu latest 07c86167cdc4 4 years ago 188MB
[root@server1 docker]# docker history busybox:latest
IMAGE CREATED CREATED BY SIZE COMMENT
59788edf1f3e 19 months ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 19 months ago /bin/sh -c #(nop) ADD file:63eebd629a5f7558c… 1.15MB
[root@server1 docker]# docker history test:v1
IMAGE CREATED CREATED BY SIZE COMMENT
ccbb07c70420 47 seconds ago sh ## 这里 29B
59788edf1f3e 19 months ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 19 months ago /bin/sh -c #(nop) ADD file:63eebd629a5f7558c… 1.15MB
对比busybox来看它多了一行,多的一行就是更改的内容,而且他们有共同的镜像层,说明这一部分他们是共享的,只保留了一份在本机中,
但是,这里我们可以看到,我们刚才的操作只记录了一个sh,如果是一些恶意操作的话,也只会显示 **sh**,在镜像安全审计的时候是不能过审的
所以,一般不建议使用,值是高速大家有这个方法。
现在我们测试一下刚才新建的镜像:
[root@server1 docker]# docker rm -f vm1 # 删除 vm1 容器
vm1
[root@server1 docker]# docker run -it --name vm1 test:v1
/ # ls
bin dev etc home proc root sys testfile tmp usr var
可以看见testfile 确实保存了下来。
Dockerfile
- 和 ansible 里面的 playbook
比较相似,把我们想要进行的操作写到这个文件里,根据这个文件构建镜像,这样的操作是透明的,大家才会放心使用。
[root@server1 ~]# mkdir docker ## 建立一个目录,将dockerfile都放到这里面
[root@server1 ~]# cd docker/
[root@server1 docker]# vim Dockerfile
内容是:
FROM busybox ## 表示基于busybox镜像
RUN echo testfile > file1 ## RUN 指运行那个命令
RUN echo testfile > file2
[root@server1 docker]# docker build -t test:v2 .
## 使用docker bulid 命令,。表示使用当前目录的dockerfile
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM busybox ## 分成三步进行
---> 59788edf1f3e # 生成镜像,对应下面busybox的id
Step 2/3 : RUN echo testfile > file1
---> Running in d47cec1fa1b3 # 使用临时容器,加进去我们的命令
Removing intermediate container d47cec1fa1b3
---> baa70e1993eb # 然后放到这个容器
Step 3/3 : RUN echo testfile > file2
---> Running in 030861184a16 #在使用临时容器,加我们第二条命令
Removing intermediate container 030861184a16
---> 69602c6919b2 ## 最后生成这个镜像,就是下面我们用docker images 可以查看的镜像
Successfully built 69602c6919b2
Successfully tagged test:v2
[root@server1 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test v2 69602c6919b2 46 seconds ago 1.15MB #就出现了
test v1 ccbb07c70420 17 minutes ago 1.15MB
busybox latest 59788edf1f3e 19 months ago 1.15MB
game2048 latest 19299002fdbe 3 years ago 55.5MB
ubuntu latest 07c86167cdc4 4 years ago 188MB
[root@server1 docker]# docker history test:v2
IMAGE CREATED CREATED BY SIZE COMMENT
69602c6919b2 3 minutes ago /bin/sh -c echo testfile > file2 9B
baa70e1993eb 3 minutes ago /bin/sh -c echo testfile > file1 9B
59788edf1f3e 19 months ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 19 months ago /bin/sh -c #(nop) ADD file:63eebd629a5f7558c… 1.15MB
后两行就是从FROM 的镜像中来的,前两行就是我们 RUN 的命令
我们在看上面创建的过程中的三布,它时根据我们的dockefile进行的,它时一行一行进行的。这就是cow的机制。
我们在加一条命令进去
[root@server1 docker]# vim Dockerfile
FROM busybox
RUN echo testfile > file1
RUN echo testfile > file2
RUN echo testfile > file3 #多了一个file3
[root@server1 docker]# docker build -t test:v3 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM busybox
---> 59788edf1f3e
Step 2/4 : RUN echo testfile > file1
---> Using cache #使用缓存
---> baa70e1993eb
Step 3/4 : RUN echo testfile > file2
---> Using cache #使用缓存
---> 69602c6919b2
Step 4/4 : RUN echo testfile > file3
---> Running in 12f9d6d2be84
Removing intermediate container 12f9d6d2be84
---> 0ba22520cbea
Successfully built 0ba22520cbea
Successfully tagged test:v3
## 这次构建是非常快的,因为前两次的更改我们已经做过了,所以再次创建,如果有相同的镜像层的话,它会直接从缓存中读去,不会去创建临时容器了。
## 修改镜像名称
docker tag 【镜像ID】【镜像名称】:【tag版本信息】
docker tag 8ef375298394 mysql:v5.7
dockerfile的具体写法
USER
USER指令用于指定容器执行程序的用户身份,默认是 root用户。
在docker run 中可以通过 -u 选项来覆盖USER指令的设置。
举例:docker run -i -t -u mysql newmysqldb /bin/bash
COPY
[root@server1 docker]# docker rmi test:v1
Untagged: test:v1
Deleted: sha256:ccbb07c70420075c8e33dd47859616658344cfd0fd91cae92adff74d209985df
Deleted: sha256:2e111e5c875c6ac9867ca03157acb0a1b96dfcbc4c21d2d170dda3536ea40905
[root@server1 docker]# docker rmi test:v2
Untagged: test:v2
[root@server1 docker]# docker rmi test:v3
# 先删除之前的几个新镜像。
[root@server1 docker]# echo helloworld > testfile 创建testfile文件
[root@server1 docker]# vim Dockerfile
FROM busybox
COPY testfile /tmp 将testfile 复制到/tmp 目录下去
[root@server1 docker]# docker build -t test:v1 . # 构建
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM busybox
---> 59788edf1f3e
Step 2/2 : COPY testfile /tmp
---> e56af2cf81bd
Successfully built e56af2cf81bd
Successfully tagged test:v1
[root@server1 docker]# docker history test:v1
IMAGE CREATED CREATED BY SIZE COMMENT
e56af2cf81bd 10 seconds ago /bin/sh -c #(nop) COPY file:b365b01e2b088c0a… 11B # 这时我们新加的命令
59788edf1f3e 19 months ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 19 months ago /bin/sh -c #(nop) ADD file:63eebd629a5f7558c… 1.15MB
[root@server1 docker]# docker run -it --name vm1 test:v1 # 运行
/ # ls
bin dev etc home proc root sys tmp usr var
/ # cd /tmp/
/tmp # ls
testfile
/tmp # cat testfile
helloworld #这就是我们copy的文件
/tmp #
这就是copy的用法,可以把本机的文件在构建中拷贝到容器中去,方便了我们的部署,比如部署apache时
或nginx,在创建的同时就可以把默认发布页面发布过去
ADD
ADD相比与COPY 只多了一个功能,就是在拷贝的过程中解压文件。
现在当前目录获取一个nginx压缩包:
[root@server1 docker]# vim Dockerfile
FROM busybox
COPY testfile /tmp
ADD nginx-1.18.0.tar.gz /tmp
[root@server1 docker]# docker build -t test:v2 . # 建立
Sending build context to Docker daemon 1.043MB
Step 1/3 : FROM busybox
---> 59788edf1f3e
Step 2/3 : COPY testfile /tmp
---> Using cache
---> e56af2cf81bd
Step 3/3 : ADD nginx-1.18.0.tar.gz /tmp
---> a66cd7e60132
Successfully built a66cd7e60132
Successfully tagged test:v2
[root@server1 docker]# docker run -it --name vm1 test:v2 # 运行
docker: Error response from daemon: Conflict. The container name "/vm1" is already in use by container "9ba3b48b4f2ae493979ad9d871634c28c3b11a9b67920c87b66cc407389866ce". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'. # 这里起冲突了,vm1这个名字用了
[root@server1 docker]# docker rm -f vm1
vm1
[root@server1 docker]# docker run -it --name vm1 test:v2
/ # cd tmp/
/tmp # ls
nginx-1.18.0 testfile
/tmp # cd nginx-1.18.0/
/tmp/nginx-1.18.0 # ls
CHANGES CHANGES.ru LICENSE README auto conf configure contrib html man src
可以看出在复制的时候将压缩包解压好了。
数据卷VOLUME
[root@server1 docker]# vim Dockerfile
FROM busybox
COPY testfile /tmp
ADD nginx-1.18.0.tar.gz /tmp
VOLUME ["/data"] 表示创建 /data 这个目录
[root@server1 docker]# docker build -t test:v3 .
[root@server1 docker]# docker run -it --name vm2 test:v3
/ # ls
bin data dev etc home proc root sys tmp usr var
# 就出现了data 目录,这个目录其实和我们的真实主机是相关联的
我们进行查看:
[root@server1 docker]# docker inspect
这里我们可以看到,这个数据卷存放在我们真实主机的这个目录中,它是数据卷的挂载,它会在宿主机上生成目录,并且和容器中的目录关联。在主机上创建的东西,在容器中就可以看到。
我们创建一个文件:
[root@server1 docker]# cd /var/lib/docker/volumes/91f0897dbeda40ac75f20603dccb0459920191144c77eea663cccde1307b7f1d/_data
[root@server1 _data]# touch file1 file2
[root@server1 _data]# docker attach vm2
You cannot attach to a stopped container, start it first
[root@server1 _data]# docker start vm2
vm2
[root@server1 _data]# docker attach vm2
/ # ls
bin data dev etc home proc root sys tmp usr var
/ # cd data/
/data # ls
file1 file2
## 果然可以看到,两边的操作是对应的,
我们还可以将其挂载到我们想要的位置,因为现在的这个挂载点的名字太长了。
[root@server1 _data]# docker run -it --name vm3 -v /opt/data:/data test:v3
/ # ls # -v指定挂载点 ,:前面为宿主机目录,会自动创建,后面为容器的目录
bin data dev etc home proc root sys tmp usr var
/ # cd data/
/data # ls
/data # ls # 看不到了,因为对应关系变了,所以看不到之前那个目录创建的文件了
/data # touch westos
/data # [root@server1 _data]# ls /opt/data # 按 CTRL + p + q可保存状态退出,用attach在连接。
westos
## 就可以看到了
WORKDIR
工作目录,这个参数是用来为ADD RUN COPY 这几个命令设置在镜像中的工作目录的,不存在会自动新建,相当于cd命令。比如在拷贝的过程中我们要进入到目录执行命令,我们是不能用cd命令的,这个workdir就可以帮助我们进去,再执行我们的命令。
CMD 和 ENTRYPOINT 和 RUN
RUN:执行命令并创建新的Image Layer
CMD:设置容器启动后默认执行的命令和参数
如果docker run指定了其他命令,CMD命令被忽略
如果定义了多个CMD, 只有最后一个会执行
ENTRYPOINT:设置容器启动时运行的命令
让容器以应用程序或者服务的形式运行
不会被忽略,一定会执行
dockerfile中只能指定一个 ENTRTPOINT ,否则只会执行最后一个
-
CMD 和 RUN 的区别
两者都是用于执行命令,区别在于执行命令的时机不同,RUN命令适用于在 docker build 构建docker镜像时执行的命令,而CMD命令是在 docker run 执行docker镜像构建容器时使用,可以动态的覆盖CMD执行的命令。 -
CMD 和 ENTRYPOINT的区别
首先,CMD命令是用于默认执行的,且如果写了多条CMD命令,则只会执行最后一条,如果后续存在ENTRYPOINT命令,则CMD命令或被充当参数或者覆盖,而且Dockerfile中的CMD命令最终可以被在执行 docker run命令时添加的命令所覆盖。而ENTRYPOINT命令则是一定会执行的,一般用于执行脚本
dockerfiler的俩种格式
shell 格式
一般会有以下两种书写格式:
Shell格式:
在shell写法中,如果存在 ENTRYPOINT命令,则不管是在Dockerfile中存在CMD命令也好,还是在 docker run执行的后面添加的命令也好,都不会被执行。如果不存在 ENTRYPOINT命令,则可以被 docker run后面设置的命令覆盖,实现动态执行命令操作。
RUN apt-get install -y vim
CMD echo "hello docker"
ENTRYPOINT echo "hello docker"
Exec格式:
RUN ["apt-get","install","-y","vim"]
CMD ["/bin/echo","hello docker"]
ENTRYPOINT ["/bin/echo","hello docker"]
ENTRYPOINT ["/bin/echo","hello $name"]
这样的写法只会打印出 “hello $name”,原因是它只是在执行echo命令,并不是执行shell。
意思是说,我们不是在shell里执行echo,只是单纯的执行echo,所以不会替换变量。想要改成可执行的shell,需要改写成以下形式:
FROM centos
ENV name Docker
ENTRYPOINT ["/bin/bash","-c","echo hello $name"]
[root@server1 docker]# vim Dockerfile
FROM busybox
ENV name world # 设置一个环境变量
ENTRYPOINT echo "hello, $name" # 应该输出hello,world
[root@server1 docker]# docker build -t test:v4 .
Sending build context to Docker daemon 1.043MB
Step 1/3 : FROM busybox
---> 59788edf1f3e
Step 2/3 : ENV name world
---> Running in 6342b3e9af3a
Removing intermediate container 6342b3e9af3a
---> d84029daefc2
Step 3/3 : ENTRYPOINT echo "hello, $name"
---> Running in c53c110b2859
Removing intermediate container c53c110b2859
---> a7804adb5af4
Successfully built a7804adb5af4
Successfully tagged test:v4
[root@server1 docker]# docker run --rm test:v4 --rm 表示一次性容器,运行完后删除
hello, world
[root@server1 docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
290b4854763f test:v3 "sh" 20 minutes ago Exited (0) 8 minutes ago vm3
c6fb50481e50 test:v3 "sh" 31 minutes ago Exited (0) 22 minutes ago vm2
75b9b11dd8bb test:v2 "sh" 36 minutes ago Exited (0) 35 minutes ago vm1
## 删除了
exec 格式
[root@server1 docker]# vim Dockerfile
FROM busybox
ENV name world
ENTRYPOINT ["/bin/sh","-c","echo hello,$name"]
[root@server1 docker]# docker build -t test:v6 .
Successfully built 9ddd8e36cd7b
Successfully tagged test:v6
[root@server1 docker]# docker run --rm test:v6
hello,world
[root@server1 docker]# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]
[root@server1 docker]# docker build -t test:v7 .
Successfully built 1e98b0485f36
Successfully tagged test:v7
[root@server1 docker]# docker run --rm test:v7
hello world
[root@server1 docker]# docker run --rm test:v7 westos
hello westos
## 可以看出,当run 后面不接参数时,就使用CMD的参数,接时就会替换掉CMD的参数
exec格式时比较推荐使用的,比较整齐。
更多推荐
所有评论(0)