文章目录
1.DockerFile是什么
当我们从docker镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过以下两种方式对镜像进行更改。
1.从已经创建的容器中更新镜像,并且提交这个镜像
2.使用 Dockerfile 指令来创建一个新的镜像Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。DockerFile是描述镜像的一种文件!
DockerFile是镜像的说明书,里面有一系列的执行,告诉Docker如何构建镜像!
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
-
Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
-
在Docker中创建镜像最常用的方式,就是使用Dockerfile。Dockerfile是一个Docker镜像的描述文件,我们可以理解成火箭发射的A、B、C、D…的步骤。Dockerfile其内部包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
-
Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
-
Docker容器,容器是直接提供服务的。
-
构建三步骤
编写Dockerfile文件 -----> 编写DockerFile文件
docker build -----> 构建镜像
docker run -----> 使用镜像启动容器
DockerFile就是镜像的描述文件!
2.DockerFile文件什么样
2.1.以我们熟悉的CentOS为例
网站:https://hub.docker.com/_/centos/
2.2.一个Dockerfile的示例如下所示
#基于centos镜像
FROM centos
#维护人的信息
MAINTAINER The CentOS Project <303323496@qq.com>
#安装httpd软件包
RUN yum -y update
RUN yum -y install httpd
#开启80端口
EXPOSE 80
#复制网站首页文件至镜像中web站点下
ADD index.html /var/www/html/index.html
#复制该脚本至镜像中,并修改其权限
ADD run.sh /run.sh
RUN chmod 775 /run.sh
#当启动容器时执行的脚本文件
CMD ["/run.sh"]
由上可知,Dockerfile结构大致分为四个部分:
(1)基础镜像信息
(2)维护者信息
(3)镜像操作指令
(4)容器启动时执行指令。
Dockerfile每行支持一条指令,每条指令可带多个参数,支持使用以#号开头的注释。下面会对上面使用到的一些常用指令做一些介绍。
2.3.DockerFile构建过程解析
-
Dockerfile内容基础知识
1:每条保留字指令都必须为大写字母且后面要跟随至少一个参数
2:指令按照从上到下,顺序执行
3:#表示注释
4:每条指令都会创建一个新的镜像层,并对镜像进行提交 -
Dockerfile内容基础知识
1:docker从基础镜像运行一个容器
2:执行一条指令并对容器作出修改
3:执行类似docker commit的操作提交一个新的镜像层
4:docker再基于刚提交的镜像运行一个新容器
5:执行dockerfile中的下一条指令直到所有指令都执行完成 -
小结
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段:
1:Dockerfile是软件的原材料
2:Docker镜像是软件的交付品
3**:Docker容器**则可以认为是软件的运行态。
3.Dockerfile常用指令
3.1.FROM
指明构建的新镜像是来自于哪个基础镜像,例如:
FROM centos:6
基础镜像不存在会在Docker Hub上拉去(一般会是文件的第一个指令) 使用格式:
FROM <镜像>:[tag]
3.2.MAINTAINER
指明镜像维护着及其联系方式(一般是邮箱地址),例如
MAINTAINER BRUCELIU<bruceliu9527@163.com>
不过,MAINTAINER并不推荐使用,更推荐使用LABEL来指定镜像作者,例如:
LABEL maintainer="bruceliu.cn"
[逐渐废弃] LABLE --替代MAINTANIER 具体使用: LABLE maintainer=“作者信息”
3.3.RUN
RUN 指令是用来执行命令行命令的。由于命令行的强大能力,RUN 指令在定制镜像时是最常用的指令之一。其格式有两种:
• shell 格式:RUN <命令>,就像直接在命令行中输入的命令一样。刚才写的 Dockerfile 中的 RUN 指令就是这种格式.
• exec 格式:RUN [“可执行文件”, “参数1”, “参数2”],这更像是函数调用中的格式。
使用格式:
RUN RUN ["","",""]
构建镜像时运行的Shell命令,例如:
RUN ["yum", "install", "httpd"]
RUN yum install httpd
RUN 就像 Shell 脚本一样可以执行命令,那么我们是否就可以像 Shell 脚本一样把每个命令对应一个 RUN 呢?比如
这样:
RUN apt-get update
RUN apt-get install -y gcc libc6-dev make
RUN wget http://download.redis.io/releases/redis-4.0.1.tar.gz
RUN tar xzf redis-4.0.1.tar.gz
RUN cd redis-4.0.1
Dockerfile 中每一个指令都会建立一层,RUN 也不例外。每一个 RUN 的行为,和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像。 而上面的这种写法,创建了 多 层镜像。这是完全没有意义的,而且很多运行时不需要的东西,都被装进了镜像里,比如编译环境、更新的软件包等等。结果就是产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。 这是很多初学 Docker 的人常犯的一个错误。
Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层。上面的Dockerfile 正确的写法应该是这样
FROM centos
RUN apt-get update \
&& apt-get install -y gcc libc6-dev make \
&& wget http://download.redis.io/releases/redis-4.0.1.tar.gz \
&& tar xzf redis-4.0.1.tar.gz \
&& cd redis-4.0.1
首先,之前所有的命令只有一个目的,就是编译、安装 redis 可执行文件。因此没有必要建立很多层,这只是一层的事情。因此,这里没有使用很多个 RUN 对一一对应不同的命令,而是仅仅使用一个 RUN 指令,并使用 && 将各个所需命令串联起来。将之前的 7 层,简化为了 1 层。
在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写Shell 脚本,而是在定义每一层该如何构建且,这里为了格式化还进行了换行。Dockerfile 支持 Shell 类的行尾添加 \ 的命令换行方式,以及行首 # 进行注释的格式。良好的格式,比如换行、缩进、注释等,会让维护、排障更为容易,这是一个比较好的习惯。
3.4.CMD
启动容器时执行的Shell命令,例如:
CMD ["-C", "/start.sh"]
CMD ["/usr/sbin/sshd", "-D"]
CMD /usr/sbin/sshd -D
3.5.EXPOSE
声明容器运行的服务端口,为容器打开指定要监听的端口以实现与外部通信,例如:
EXPOSE 80 443
3.6.ENV
ENV指令可以用于为docker容器设置环境变量 ENV设置的环境变量,可以使用 docker inspect命令来查看。同时还可以使用docker run --env =来修改环境变量。
具体用法:
ENV JAVA_HOME /usr/local/jdk
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/:$JRE_HOME/lib/
ENV PATH $PATH:$JAVA_HOME/bin/
3.7.ADD
类似COPY命令,拷贝文件或目录到镜像中,例如:
ADD <src>...<dest>
ADD html.tar.gz /var/www/html
ADD https://xxx.com/html.tar.gz /var/www/html
3.8.COPY
拷贝文件或目录到镜像中,用法同ADD,只是不支持自动下载和解压,例如:
COPY ./start.sh /start.sh
3.9.ENTRYPOINT
启动容器时执行的Shell命令,同CMD类似,只是由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序,例如:
ENTRYPOINT ["/bin/bash", "-C", "/start.sh"]
ENTRYPOINT /bin/bash -C '/start.sh'
PS:Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效。
3.10. VOLUME
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。例如:
VOLUME ["/var/lib/mysql"]
只能定义docker管理的卷: VOLUME /data/mysql运行的时候会随机在宿主机的目录下生成一个卷目录!
一般不会在Dockerfile中用到,更常见的还是在docker run的时候指定-v数据卷。
3.11 USER
为RUN、CMD和ENTRYPOINT执行Shell命令指定运行用户,例如:
USER <user>[:<usergroup>]
USER <UID>[:<UID>]
USER bruceliu
3.12 WORKDIR
Docker 默认的工作目录是/,只有 RUN 能执行 cd 命令切换目录,而且还只作用在当下下的 RUN,也就是说每一个 RUN 都是独立进行的。
如果想让其他指令在指定的目录下执行,就得靠 WORKDIR。WORKDIR 动作的目录改变是持久的,不用每个指令前都使用一次 WORKDIR。
WORKDIR /usr/local/tomcat/
3.13.小总结
4.DockerFile案例
4.1.Base镜像(scratch)
Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的
4.2.自定义镜像mycentos
Docker Hub默认CentOS镜像什么情况??
- 准备编写DockerFile文件
[root@localhost myfile]# pwd
/root/myfile
[root@localhost myfile]# vi mycentos_dockerfile
- myCentOS内容DockerFile
FROM centos
MAINTAINER bruceliu<bruceliu167@126.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash
- 构建
命令:
docker build -t 新镜像名字:TAG .
会看到 docker build 命令最后有一个 .
. 表示当前目录
[root@localhost myfile]# docker build -f /root/myfile/mycentos_dockerfile -t mycentos:1.3 .
Sending build context to Docker daemon 2.048 kB
Step 1/10 : FROM centos
---> 9f38484d220f
Step 2/10 : MAINTAINER bruceliu<bruceliu167@126.com>
---> Using cache
---> 281446cb753d
Step 3/10 : ENV MYPATH /usr/local
---> Using cache
---> 2e09cdb61576
Step 4/10 : WORKDIR $MYPATH
---> Using cache
---> 4aa136d65f26
Step 5/10 : RUN yum -y install vim
---> Using cache
---> 585392f09407
Step 6/10 : RUN yum -y install net-tools
---> Using cache
---> 9c7971b08e59
Step 7/10 : EXPOSE 80
---> Using cache
---> 6741c0b61390
Step 8/10 : CMD echo $MYPATH
---> Using cache
---> fb1b4b72ba02
Step 9/10 : CMD echo "success--------------ok"
---> Using cache
---> 3d636347cc9a
Step 10/10 : CMD /bin/bash
---> Using cache
---> 720d4eb5c5f0
Successfully built 720d4eb5c5f0
- 运行
docker run -it 新镜像名字:TAG
可以看到,我们自己的新镜像已经支持vim/ifconfig命令,扩展成功了。
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/mongo latest 9c02a5a12c52 Less than a second ago 413 MB
mycentos 1.3 720d4eb5c5f0 50 minutes ago 480 MB
bruceliu/centos9527 latest 071e944a589b 8 hours ago 202 MB
bruceliu/tomcat 7-jre7 a66f9aba334d 13 hours ago 359 MB
docker.io/tomcat 7-jre7 47c156f4d4e3 5 weeks ago 359 MB
docker.io/mysql latest 7bb2586065cd 2 months ago 477 MB
docker.io/centos 7 9f38484d220f 3 months ago 202 MB
docker.io/centos latest 9f38484d220f 3 months ago 202 MB
[root@localhost ~]# docker run -it mycentos:1.3
[root@50784a17d114 local]# pwd
/usr/local
[root@50784a17d114 local]# vi 1.txt
[root@50784a17d114 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.3 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe11:3 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet)
RX packets 8 bytes 656 (656.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 656 (656.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- 列出镜像的变更历史
命令:
docker history 镜像名
[root@localhost ~]# docker history 720d4eb5c5f0
IMAGE CREATED CREATED BY SIZE COMMENT
720d4eb5c5f0 53 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/b... 0 B
3d636347cc9a 53 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "ec... 0 B
fb1b4b72ba02 53 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "ec... 0 B
6741c0b61390 53 minutes ago /bin/sh -c #(nop) EXPOSE 80/tcp 0 B
9c7971b08e59 53 minutes ago /bin/sh -c yum -y install net-tools 112 MB
585392f09407 54 minutes ago /bin/sh -c yum -y install vim 167 MB
4aa136d65f26 About an hour ago /bin/sh -c #(nop) WORKDIR /usr/local 0 B
2e09cdb61576 About an hour ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0 B
281446cb753d About an hour ago /bin/sh -c #(nop) MAINTAINER bruceliu<bru... 0 B
9f38484d220f 3 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
<missing> 3 months ago /bin/sh -c #(nop) LABEL org.label-schema.... 0 B
<missing> 3 months ago /bin/sh -c #(nop) ADD file:074f2c974463ab3... 202 MB
5.小结
希望大家关注我一波,防止以后迷路,有需要的可以加我Q讨论互相学习java ,学习路线探讨,经验分享与java Q:2415773436