利用dockerfile创建镜像
1.创建一个Dockerfile
注意:一定要创建一个新的目录 因为在构建镜像的时候,会默认把dockerfile所在的目录中的所有目录发送给docker引擎,举个例子 如果你把dockerfile放在/目录下 那么这个过程会变得非常的缓慢
[root@server3 mnt]# mkdir /mnt/docker
[root@server3 mnt]# cd docker/
[root@server3 docker]# ls
[root@server3 docker]# vim dockerfile
FROM busybox #以哪个基础镜像为模板
RUN echo testfile > file1 #在新镜像中你要执行的哪些动作
RUN echo testfile > file2
创建镜像
[root@server3 docker]# docker build -t test:v2 #镜像名称 . 代表当前目录
Sending build context to Docker daemon 2.048 kB #把dockerfile所在的目录中的所有目录发送给docker引擎
Step 1/3 : FROM busybox
---> db8ee88ad75f
Step 2/3 : RUN echo testfile > file1
---> Running in 4c00ef6f0753
---> e8a1fbac8837
Removing intermediate container 4c00ef6f0753 #临时镜像层删掉
Step 3/3 : RUN echo testfile > file2
---> Running in cd7a46bb3269
---> 5fc404485b27
Removing intermediate container cd7a46bb3269
Successfully built 5fc404485b27
- 查看刚刚镜像有没有创建成功
[root@server3 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test v2 5fc404485b27 About a minute ago 1.22 MB
test v1 c1a9c80bccb0 19 minutes ago 1.22 MB
ubuntu latest 3556258649b2 2 weeks ago 64.2 MB
busybox latest db8ee88ad75f 3 weeks ago 1.22 MB
game2048 latest 19299002fdbe 2 years ago 55.5 MB
- 查看镜像
[root@server3 docker]# docker history test:v2
IMAGE CREATED CREATED BY SIZE COMMENT
5fc404485b27 About a minute ago /bin/sh -c echo testfile > file2 9 B
e8a1fbac8837 About a minute ago /bin/sh -c echo testfile > file1 9 B
db8ee88ad75f 3 weeks ago /bin/sh -c #(nop) CMD ["sh"] 0 B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:9ceca008111a4dd... 1.22 MB
[root@server3 docker]# docker history busybox:latest
IMAGE CREATED CREATED BY SIZE COMMENT
db8ee88ad75f 3 weeks ago /bin/sh -c #(nop) CMD ["sh"] 0 B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:9ceca008111a4dd... 1.22 MB
缓存特性
再次更改dockerfile 注意:不要随便加空格(要使用缓存 之前内容不能随便更改)
[root@server3 docker]# cat dockerfile
FROM busybox
RUN echo testfile > file1
RUN echo testfile > file2
RUN echo testfile > file3
- 再次build一个镜像,会出现
Using cache
,已经缓存过的不会再缓存了
[root@server3 docker]# docker build -t test:v3 .
Sending build context to Docker daemon 2.048 kB
Step 1/4 : FROM busybox
---> db8ee88ad75f
Step 2/4 : RUN echo testfile > file1
---> Using cache #已经运行过的不再运行
---> e8a1fbac8837
Step 3/4 : RUN echo testfile > file2
---> Using cache
---> 5fc404485b27
Step 4/4 : RUN echo testfile > file3
---> Running in e2e4d6f4c565 #运行新的指令
---> edd40df71d11
Removing intermediate container e2e4d6f4c565
Successfully built edd40df71d11
说明
- 如果我们希望在构建镜像时不使用缓存,可以在docker build命令中加上
--no-cache
参数 - dockerfile中每一个指令都会创建一个镜像层,上层是依赖于下层的,无论什么时候,只要某一层发生变化,其上面所有层的缓存都会失败
- 对比来看 v2和v3 有几层是一样的 每一个RUN就会构建一层镜像
- 而且我们可以看到 每一层的操作,再次说明 共同的镜像层之间的共享的
[root@server3 docker]# docker history test:v3
IMAGE CREATED CREATED BY SIZE COMMENT
edd40df71d11 52 seconds ago /bin/sh -c echo testfile > file3 9 B
5fc404485b27 6 minutes ago /bin/sh -c echo testfile > file2 9 B
e8a1fbac8837 6 minutes ago /bin/sh -c echo testfile > file1 9 B
db8ee88ad75f 3 weeks ago /bin/sh -c #(nop) CMD ["sh"] 0 B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:9ceca008111a4dd... 1.22 MB
[root@server3 docker]# docker history test:v2
IMAGE CREATED CREATED BY SIZE COMMENT
5fc404485b27 6 minutes ago /bin/sh -c echo testfile > file2 9 B
e8a1fbac8837 6 minutes ago /bin/sh -c echo testfile > file1 9 B
db8ee88ad75f 3 weeks ago /bin/sh -c #(nop) CMD ["sh"] 0 B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:9ceca008111a4dd... 1.22 MB
本质:dockerfile中的每一层其实就是执行了一个docker commit
dockerfile常用指令
以下详细介绍dockerfile的一些常用指令 ,便于我们书写更成熟的dockerfile文件
FROM
:指定base镜像,如果本地不存在会从远程仓库下载(虚拟机要配置上网)MAINTAINER
:设置镜像的作者,比如用户邮箱等 (不是必须的)COPY
:把文件从build context复制到镜像
支持两种形式:COPY src dest 和 COPY [“src”,“dest”]
src必须指定build context中的文件或目录- 书写dockerfile
[root@server3 docker]# vim dockerfile
FROM busybox
COPY testfile /tmp
- 编辑所要复制的文档
[root@server3 docker]# vim testfile
hello~
- bulid镜像并进行查看
[root@server3 docker]# docker build -t test:v4 .
Sending build context to Docker daemon 3.072 kB
Step 1/2 : FROM busybox
---> db8ee88ad75f
Step 2/2 : COPY testfile /tmp
---> ff437a8d3732
Removing intermediate container e79887133199
Successfully built ff437a8d3732
[root@server3 docker]# docker history test:v4
IMAGE CREATED CREATED BY SIZE COMMENT
ff437a8d3732 9 seconds ago /bin/sh -c #(nop) COPY file:d93a5a916d7ae8... 7 B
db8ee88ad75f 3 weeks ago /bin/sh -c #(nop) CMD ["sh"] 0 B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:9ceca008111a4dd... 1.22
- 查看是否
COPY
成功
[root@server3 docker]# docker run -it --name vm1 test:v4
/ # ls
bin dev etc home proc root sys tmp usr var
/ # cd /tmp/
/tmp # ls
testfile
/tmp # cat testfile
hello~
建议:不用的容器和镜像,要即使删除
ADD
:用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到dest,也可以下载URL并拷贝到镜像
eg:ADD html.tar /var/www
ADD http://ip/html.tar /var/www
scp root@172.25.78.250:/mnt/nginx/nginx-1.17.4.tar.gz .
- 演示,编辑dockerfile
[root@server3 docker]# vim dockerfile
FROM busybox
COPY testfile /tmp
ADD nginx-1.15.9.tar.gz /tmp
- bulid新镜像
[root@server3 docker]# docker build -t test:v5 .
Sending build context to Docker daemon 1.036 MB
Step 1/3 : FROM busybox
---> db8ee88ad75f
Step 2/3 : COPY testfile /tmp
---> Using cache
---> ff437a8d3732
Step 3/3 : ADD nginx-1.15.9.tar.gz /tmp
---> 9db2ad29e44f
Removing intermediate container f84d556d43dc
Successfully built 9db2ad29e44f
- 验证是否
ADD
成功
[root@server3 docker]# docker run -it --name vm2 test:v5
/ # cd /tmp/
/tmp # ls
nginx-1.15.9 testfile
/tmp # cd nginx-1.15.9/
/tmp/nginx-1.15.9 # ls
CHANGES README configure man
CHANGES.ru auto contrib src
LICENSE conf htm
ENV
:设置环境变量,变量可以被后续的指令使用(不是必须的)
ENV HOSTNAME server1.example.comEXPOSE
:如果容器运行应用服务,可以把服务的端口暴露出去
[root@server3 docker]# docker history game2048
IMAGE CREATED CREATED BY SIZE COMMENT
19299002fdbe 2 years ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "se... 0 B
<missing> 2 years ago /bin/sh -c #(nop) EXPOSE 80/ tcp 0 B # 服务的端口暴露出去 方便我们去做端口映射和用户在容器启动后去访问的
<missing> 2 years ago /bin/sh -c #(nop) COPY dir:cb74e9c037a3d50... 600 kB
<missing> 2 years ago /bin/sh -c #(nop) MAINTAINER Golfen Guo <... 0 B
<missing> 2 years ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daem... 0 B
<missing> 2 years ago /bin/sh -c #(nop) EXPOSE 443/tcp 80/tcp 0 B
<missing> 2 years ago /bin/sh -c #(nop) COPY file:d15ceb73c6ea77... 1.1 kB
<missing> 2 years ago /bin/sh -c #(nop) COPY file:af94db45bb7e4b... 643 B
<missing> 2 years ago /bin/sh -c GPG_KEYS=B0F4253373F8F6F510D421... 50.1 MB
<missing> 2 years ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.11.7 0 B
<missing> 2 years ago /bin/sh -c #(nop) MAINTAINER NGINX Docker... 0 B
<missing> 2 years ago /bin/sh -c #(nop) ADD file:7afbc23fda8b0b3... 4.8 MB
-
VOLUME:
申明数据卷,通常指定的是应用的数据挂载点
目的:容器数据持久化的 -
在dockerfile中加
VOLUME ["/data"]
[root@server3 docker]# vim dockerfile
FROM busybox
COPY testfile /tmp
ADD nginx-1.15.9.tar.gz /tmp
VOLUME ["/data"] #在启动容器的时候会帮我们自动的新建
- 新建一个镜像
[root@server3 docker]# docker build -t test:v6 .
Sending build context to Docker daemon 1.036 MB
Step 1/4 : FROM busybox
---> db8ee88ad75f
Step 2/4 : COPY testfile /tmp
---> Using cache
---> ff437a8d3732
Step 3/4 : ADD nginx-1.15.9.tar.gz /tmp
---> Using cache
---> 9db2ad29e44f
Step 4/4 : VOLUME /data
---> Running in 5f03d4efc260
---> 680a9d07e8e9
Removing intermediate container 5f03d4efc260
Successfully built 680a9d07e8e9
- 运行容器
[root@server3 docker]# docker run -it --name vm2 test:v6
/ # ls
bin dev home root tmp var
data etc proc sys usr
/ # cd data/
- 我们可以通过
docker inspect 6a8af9225428
(镜像ID)这个命令看到
容器中的/data目录与宿主机上的一个新建的本地目录发生了联系
docker inspect 6a8af9225428
"Mounts": [
{
"Type": "volume",
"Name": "54322e71d6257057e0b785efdfa5853a53422a287048780753fba37df3a2470b",
"Source": "/var/lib/docker/volume/54322e71d6257057e0b785efdfa5853a53422a287048780753fba37df3a2470b/_data",
- 在宿主机中,进入到这个目录中去
cd var/lib/docker/volume/54322e71d6257057e0b785efdfa5853a53422a287048780753fba37df3a2470b/_data
注意:此目录是docker引擎自动帮我们创建出来的 目录名是随机生成的
[root@server3 /]# cd /var/lib/docker/volumes/54322e71d6257057e0b785efdfa5853a53422a287048780753fba37df3a2470b/_data
[root@server3 _data]# ls
[root@server3 _data]# touch file1
[root@server3 _data]# touch file2
[root@server3 _data]# docker attach vm2
/ # cd /data/
/data # ls
file1 file2
/data # rm -rf file1
/data # exit
[root@server3 _data]# ls
file2
WOEKDIR
:为RUN
CMD
ENTRYPOINT
ADD
COPY
指令设置镜像中的当前工作目录(类似于cd ),如果目录不存在会自动创建RUN
:在容器中运行命令并创建新的镜像层,常用于安装包
每一个RUN指令都会构建一层镜像层 尽可能将 多个命令放在一个RUN指令下RUN yum install -y vim
CMD
与ENTRYPOINT
:这两个指令都是用于设置容器启动后执行的命令
但CMD
会被docker run后面的命令覆盖,而ENTRYPOINT
不会被忽略,一定会被执行
docker run后面的参数可以传递给ENTRYPOINT
指令当作参数 dockerfile中只能指定一个ENTRYPOINT
,如果指定了很多,只有最后一个有效
CMD与ENTRYPOINT(容器启动后要运行的!!)
RUN :在创建容器的时候!!!(在容器中)
shell 和 exec两种书写格式
- shell方式
[root@server3 docker]# cat dockerfile
FROM busybox
ENV name world #ENV:定义变量
ENTRYPOINT echo "hello,$name"
[root@server3 docker]# docker build -t test:v8 .
Sending build context to Docker daemon 1.036 MB
Step 1/3 : FROM busybox
---> db8ee88ad75f
Step 2/3 : ENV name world
---> Using cache
---> 9771be0e3225
Step 3/3 : ENTRYPOINT /bin/echo hello,$name
---> Running in 6bc8e3d7e2d8
---> 77cecb1b6c1c
Removing intermediate container 6bc8e3d7e2d8
Successfully built 77cecb1b6c1c
- 发现问题 变量无法被解析
[root@server3 docker]# docker run --rm test:v8
hello,$name
- exec的方式
[root@server3 docker]# cat dockerfile #
FROM busybox
ENV name world
ENTRYPOINT ["/bin/echo","hello,$name"]
shell格式底层会掉用/bin/sh -c 来执行命令,可以解析变量,而exec格式不会
[root@server3 docker]# docker build -t test:v9 .
Sending build context to Docker daemon 1.036 MB
Step 1/3 : FROM busybox
---> db8ee88ad75f
Step 2/3 : ENV name world
---> Using cache
---> 9771be0e3225
Step 3/3 : ENTRYPOINT /bin/sh -c echo hello,$name
---> Running in 5ab8da5fc8ca
---> 6f26d3c56e7e
Removing intermediate container 5ab8da5fc8ca
Successfully built 6f26d3c56e7e
exec格式时,ENTRYPOINT可以通过CMD提供的额外参数,CMD的额外参数可以在容器启动时动态替换,在shell格式时ENTRYPOINT会忽略任何CMD或docker run提供的参数
[root@server3 docker]# docker run --rm test:v10
hello world
- 比较
CMD
和ENTRYPOINT
[root@server3 docker]# cat dockerfile
FROM busybox
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]
验证
[root@server3 docker]# docker run --rm test:v10 westos
hello westos
# westos 覆盖了dockerfile CMD后面的值