本系列主要分为以下六大部分,正在更新中,尽请期待!
点击关注本专栏
提示:已经更新的或正在更新的文章前面打勾了哈!
到目前为止我们构建镜像的方法无疑是使用docker commit
命令基于已有镜像的容器来构建镜像,但是这样的缺点也很明显。
使用docker commit
命令创建容器时所有操作都是在容器内部进行的,其他人或者自己在较长时间后也不知道这个镜像是怎么做出来的,并且我们需要在容器内操作麻烦,效率低,不灵活。
所以我们一般推荐使用Dockerfile来创建镜像。
Dockerfile文件本质是一个文本格式的配置文件,用户可以使用 Dockerfile 来快速创建自定义的镜像。
Dockerfile由一行行命令语句组成,并且支持以#开头的注释行。
一般而言, Dockerfile主体内容分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。
#正确的做法
bash RUN apt-get update && apt-get install vim,
#不提倡的做法
bash RUN apt-get update RUN apy-get install vim
接下来我们结合一个Dockerfile的例子来看看它的结构:
#========基础镜像==========
# Docker file for Hexo 3
FROM ubuntu:16.04
#=========维护者信息==========
MAINTAINER MUNGO
#=======镜像的操作命令========
# use aliyun's mirror for faster download speed
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
# add pandoc repository
RUN sed -i 's/deb mirror.lupaworld.com/ubuntu vivid main universe/g' /etc/apt/sources.list
# instal basic tool
RUN apt-get update && \
apt-get install -y nodejs curl git-core pandoc yui-compressor && \
update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10 && \
curl -L https://npmjs.org/install.sh | sh && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
ENV HEXO_VERSION 3.0.0
# install hexo
RUN npm install -g hexo@${HEXO_VERSION}
# set base dir
RUN mkdir /hexo
# set home dir
WORKDIR /hexo
EXPOSE 4000
#=========容器启动时执行的命令===============
CMD ["/bin/bash"]
在这个例子中可以清晰的看到Dockerfile主体内容是由四部分组成的。
FROM
功能是指定所创建镜像的基础镜像,并且必须是第一条指令。如果在同一个 Dockerfile中创建多个镜像时,可以使用多个FROM指令(每个镜像一次),如下:
FROM <image>
FROM <image>:<tag>
FROM <image>:<digest>
如果不以任何镜像为基础,那么写法为: FROM scratch
,同时意味着接下来所写的指令作为镜像的第一层开始。
ARG
功能是定义创建镜像过程中使用的变量,ARG命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg
来指定参数,如下:
#定义变量key1
ARG key1
#定义变量key2,并赋默认值value2
ARG key2=value2
ENV
指定环境变量,在镜像生成过程中会被后续RUN 指令使用,在镜像启动的容器中也会存在。使用语法如下:
#一次设置一个变量
ENV <key> <value>
ENV <key>=<value>
#一次设置多个变量
ENV <key1>=<value1> <key2>=<value2> ..
EXPOSE
功能是声明镜像内服务监听的端口。注意该指令只是起到声明作用,并不会自动完成端口映射。
#设置监听端口为80
EXPOSE 80/tcp
如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上-P
参数
ENTRYPOINT
功能是指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数。使用格式如下:
#类似于函数调用,可将executable理解成为可执行文件,后面就是两个参数。
ENTRYPOINT ["executable","param1","param2"]
#后面直接跟shell命令
ENTRYPOINT command param1 param2
每个 Dockerfile中只能有一个 ENTRYPOTNT
,当指定多个时只有最后一个起效。
VOLUME
功能是创建一个数据卷挂载点。运行容器时可以从本地主机或其他容器挂载数据卷,一般用来存放数据库和需要保持的数据等。使用格式如下:
VOLUME ["/data"]
一般的使用场景为需要持久化存储数据时。
USER
功能是设置启动容器的用户,可以是用户名和UID,使用格式如下:
#用户名
USER username
#UID
USER UID
当服务不需要管理员权限时,可以通过该命令指定运行用户,并且可以在 Dockerfile中创建所需要的用户。
RUN
功能是运行指定命令。每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像层。当命令较长时可以使用 \ 来换行。使用格式为:
#后面直接跟shell命令
RUN <command>
#类似于函数调用,可将executable理解成为可执行文件,后面就是两个参数。
RUN ["executable","param1","param2"]
RUN的默认权限是sudo
。需要注意的是,如果你需要执行多个RUN操作,那最好把它们合并在一行 (用&&连接),因为每执行一次RUN就会在docker上新建一层镜像,所以分开来写很多个RUN的结果就是会导致整个镜像无意义的过大膨胀;
CMD
功能是指定启动容器时默认执行的命令。使用格式如下:
#类似于函数调用,可将executable理解成为可执行文件,后面就是两个参数
CMD ["executable","param1","param2"]
#与第一种类似,可执行文件+参数
CMD ["param1',"param2"]
#shell这种执行方式和写法
CMD command param1 param2
参数一定要用双引号,千万不能写成单引号。原因是参数传递后,docker解析的是一个JSON数组。
并且每个 Dockerfile只能有一条CMD命令,如果指定了多条命令只有最后一条会被执行。
关于RUN和CMD:
RUN
是构容器时就运行的命令以及提交运行结果;
CMD
是容器启动时执行的命令,在构建时并不运行,构建时仅仅指定了这个命令到底是个什么样子;
ADD
功能是添加内容到镜像,如果是压缩文件,则会自动进行解压。使用格式如下:
#路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径
#可以是一个本地文件或者是一个本地压缩文件,还可以是一个url
ADD <src> <dest>
ADD ["" ,"" ]
COPY
复制内容到镜像,COPY的
只能是本地文件,而且不能自动解压。使用格式如下:
COPY <src> <dest>
COPY ["" ,"" ]
将文件作为一个新的层添加到镜像中。通常使用 COPY 指令将应用代码赋值到镜像中。
对Dockerfile进行基本的学习之后,那么我们怎么样才能使用Dockerfile来创建镜像呢?
接下来我带你手把手创建一个镜像,并且使用这个镜像创建容器且运行:
#创建文件夹
mkdir httpd -p;
#进入文件夹
cd httpd;
如下:
docker pull centos:7
如下:
vim index.html
#页面内容
test page
如下:
vim dockerfile
#文件内容
#使用centos:7 镜像
FROM centos:7
#执行的安装命令
RUN yum install httpd -y
#声明端口
EXPOSE 80
#拷贝网页文件
COPY index.html /home/myroot/httpd/index.html
#前台执行命令
CMD ["/home/myroot/httpd","-D","FOREGROUND"]
如下:
# v66是标签名
docker build -t httpd:v66 .
docker images
docker run -itd -p 66:80 f3e5bafcdba6
最后进行访问http://本机ip:66
,如果看到一下界面说明你成功了!
那么我们如何才能撰写出高效的 Dockerfile呢?
docker build
时忽略的路径和文件,避免发送不必要的数据内容,从而加快整个镜像创建过程。/var/ cache/apt
下面会缓存了一些安装包;. dockerignore
文件指定等;看看本专栏文章有哪些吧!
本系列文章目录:
点击关注本专栏
可以看出来本系列文章将会带你从-1到1的学习云原生的,一起加油吧!
本篇我们一起学习了Dockerfile的相关知识,在使用Dockerfile构建镜像的过程中,我们可以体会到 Docker镜像在使用上一处修改代替大量更新的灵活之处。