Dockerfile 编写
先放个简单例子
#get base docker
FROM centos/systemd
# Maintainer massage
MAINTAINER xxx@xxx.com
# install foundamental packages and utilities packages
RUN yum install -y cmake make vim tree wget curl gzip zip unzip git sox && \
yum install -y openssl openssh-server openssh-client
# Switch working path to /root
WORKDIR /root
# copy loacl file to docker
ADD jdk-8u45-linux-x64.tar.gz /usr/local
ENV JAVA_HOME /usr/local/jdk1.8.0_45
# set Environment
ENV CPPFLAGS -UPHNALG
WORKDIR /var/localbag/lame-3.100/
RUN ./configure --prefix=/usr/local/ --enable-shared && \
make && make install
# expose port 8222
EXPOSE 8222
# like as CMD,but be not covered by CMD
ENTRYPOINT ["/root/run.sh"]
# startup script when docker running
CMD ["/usr/sbin/init","/root/run.sh"]
从上面得基础示例可以看出Dockerfile主要分为四个部分:
- 基础镜像信息
FROM
FROM 是为了指明构建的镜像是出自哪个基础镜像的,在此基础上加上些保证我们应用服务可以正常运行的软件,如上面示例的cmake、make、vim等,
docker基础镜像可以从docker-hub上寻找拉取下载
- 维护者信息
MAINTAINER / LABEL
通过MAINTAINER / LABEL来指明该镜像的维护者或其联系方式;
LABEL可以给镜像增加(多个)标签记录信息
- 镜像操作指令
RUN
用于构建镜像时运行的shell命令,如安装扩展软件,环境配置等
[^ 注1]: 你应该避免使用RUN apt-get upgrade
或者dis-upgrade
, 因为父镜像中许多"基本的"(essential)包不能在容器中升级。
[^ 注2]: 使用RUN apt-get update && apt-get install -y
可以确保你的Dockerfile
安装最新版本的软件包而无需编码或手动干预。
ADD / COPY
ADD和COPY都可以拷贝文件或者目录到镜像中,但是ADD后如果是URL那么就会自动下载或者是自动解压,而COPY不支持自动下载和解压
WORKDIR
用于设置工作目录,和RUN cd都有切换目录的作用,但是WORKDIR为docker进行工作目录切换,而RUN cd只是在RUN中的一步,暂时切换,RUN执行结束后失效
ENV
设置环境变量 ,如上例ENV CPPFLAGS -UPHNALG
VOLUME
指定容器挂载点到宿主机自动生成的目录或其他容器,和docker run -v效用一样,但是后者更常见
- 容器启动时执行命令
EXPOSE
声明容器运行服务端口
ENTRYPOINT
启动容器时执行的shell命令或是脚本,由ENTRYPOINT启动的命令或是脚本不会被覆盖,ENTRYPOINT可以有多条,但是只有最后一条会生效
CMD
启动容器时执行的shell命令或是脚本,Dockerfile中CMD可以有多条,但是只有最后一条会生效
到此,创建好Dockerfile后,便可以创建镜像了
docker build -t test-docker:v0.1 .
镜像名不能有大写哦
注:
- docker 层数最小化
在保证Dockerfile可读性(从而可以长时间维护)的同时也需要兼顾dockerfile的层数最小化。
- 构建缓存
在构建镜像的过程中,Docker会逐句读取你Dockerfile中的指令按指定的顺序执行。因为每个指令都会被检查Docker会在它的缓存中查找可以重用的现有镜像,而不是创建一个新的(重复的)镜像。如果你根本不想使用缓存,你可以对 docker build
命令使用 --no-cache=ture
参数。
- 检查缓存
除了ADD
和COPY
命令以外,缓存检查将不会检查容器中的文件来确定缓存匹配。比如,当处理一个RUN apt-get -y update
容器中的文件更新将不会被检查来确定是否命中已存在缓存。在这种情况下只有命令字符串自己将被用来查找匹配。一旦缓存失效,那么后面所有的Dockerfile命令将会生成新的镜像而不会使用缓存。