Dockerfile
文件包含了构建镜像的一套完整指令FROM
指令开头,其实也是允许这个之前定义变量#
是注释,但是要以这个开头的才是。行中其他位置被视为参数的一部分escape=
通过:docker build
原理:通过 Dockerfile 文件和构建上下文(build context)构建镜像
构建上下文
上下文是由文件路径或者一个 URL 定义的一组文件
构建上下文以递归方式处理,本地路径包括其中的任何子目录,URL 包括仓库及其子模块
示例
使用当前目录作为上下文的构建语句:docker build -t 镜像标识 .
镜像构建过程
这边以centos的镜像作为构建基础
设置基础镜像
FROM <image> [AS name]
示例
运行命令
RUN <command>
RUN ["exec","param1","param2"]
示例
RUN ["/bin/bash", "-c", "echo hello,world"]
指定容器启动时默认执行的命令
CMD ["exec","param1","param2"] ## 首选
CMD ["param1","param2"] ## 提供给 ENTRYPOINT 指令的默认参数
CMD command param1 param2 ## shell 格式
示例
向镜像添加元数据信息
LABEL kye=value kye=value kye=value...
示例
声明容器运行时监听的端口
EXPOSE <port>
指定环境变量
ENV key value ### 单个环境变量
ENV key=value key=value key=value ### 多个环境变量
示例
ARG version=7
FROM centos:$version
LABEL name=whale mail=565616251@qq.com info="then is a test"
COPY index.html /home/html/
EXPOSE 80/tcp 8088/udp
ENV var1=hello var2=world var3="hello world"
RUN ["/bin/bash","-c","echo ${var1}"]
RUN ["/bin/bash","-c","echo hello,world"]
CMD ["/bin/bash","-c","echo ${var1},${var2}"]
将源文件复制到容器内
COPY [--chown=<user>:<group>] <src>...<dest> #### chown只用于linux容器
COPY [--chown=<user>:<group>] ["" ,..."" ] #### 路径如果有空格字符,要用这种形式
示例
ARG version=7
FROM centos:$version
LABEL name=whale mail=565616251@qq.com info="then is a test"
COPY ind* /home/html/
EXPOSE 80/tcp 8088/udp
ENV var1=hello var2=world
CMD ["/bin/bash","-c","cat /home/html/index.html"]
将源文件复制到容器
ADD [--chown=<user>:<group>] <src>...<dest> #### chown只用于linux容器
ADD [--chown=<user>:<group>] ["" ,..."" ] #### 路径如果有空格字符,要用这种形式
配置容器的默认入口
ENTRYPOINT ["exec","param1","param2"] #### 首选exec格式
ENTRYPOINT command param1 param2 #### shell 格式
创建挂载点
VOLUME ["/data"]
示例
ARG version=7
FROM centos:$version
LABEL name=whale mail=565616251@qq.com info="then is a test"
COPY index.html /home/html/
EXPOSE 80/tcp 8088/udp
ENV var1=hello var2=world
VOLUME ["/home/html/"]
CMD ["/bin/bash","-c","cat /home/html/index.html"]
配置工作目录
WORKDIR /path/xxx/xxxx
示例
ARG version=7
FROM centos:$version
LABEL name=whale mail=565616251@qq.com info="then is a test"
WORKDIR /
RUN pwd
COPY index.html /home/html/
EXPOSE 80/tcp 8088/udp
ENV var1=hello var2=world
VOLUME ["/home/html/"]
WORKDIR /home/html
CMD ["/bin/bash","-c","cat index.html"]
设置运行镜像时使用的用户名
USER <user>:<group>
示例
ARG version=7
FROM centos:$version
LABEL name=whale mail=565616251@qq.com info="then is a test"
RUN useradd whale
USER whale:whale
COPY index.html /home/html/
EXPOSE 80/tcp 8088/udp
ENV var1=hello var2=world
VOLUME ["/home/html/"]
WORKDIR /home/html
CMD ["/bin/bash","-c","id"]
定义构建时候的变量
ARG <name>[=<value>]
指定命令的 shell 格式
SHELL ["exec","parameters"]
RUN、CMD、ENTRYPOINT
这些指令都会用到 exec 和 shell 两种格式
#### exec的一般写法:直接调用命令,不会被shell进行解析,也识别不了ENV指令的环境变量,除非是 shell 执行的
<指令> ["exec", "param1", "param2" ,......]
ENTRYPOINT ["/bin/echo", "Hello,World"]
#### shell 的一般写法:底层直接调用的是/bin/sh -c 来执行的
<指令> <command>
ARG version=7
FROM centos:$version
LABEL name=whale mail=565616251@qq.com info="then is a test"
ENTRYPOINT ["/bin/echo", "hello"]
CMD [" world"]
注意点
docker 17.05以上才支持
不用多阶段构建的解决方案
使用多阶段构建
####
ARG version=7
FROM centos:$version
LABEL name=whale mail=565616251@qq.com info="then is a test"
COPY index.html /home/html/
FROM centos:6
COPY --from=0 /home/html/index.html /home/ ### 从前一阶段复制到新的阶段
CMD ["/bin/bash","-c","cat /home/index.html"]
为每个构建阶段命名
这里使用c语言环境进行构建演示
FROM gcc:latest as builder
WORKDIR /app
COPY myapp.c /vim app
RUN gcc -o myapp myapp.c
FROM centos:7
WORKDIR /
COPY --from=builder /app/myapp .
CMD ["./myapp"]
echo -e "FROM xxx \nRUN xxxx" | docker build -
选择基础镜像
几乎所有开发技术都有自己的基础镜像,比如:java、python、node.js等,如果不直接使用这些镜像,就需要从基础操作系统镜像开始安装所有的依赖,最常见的就是 ubuntu 操作系统作为基础镜像
安装必要的软件
如果有必要,需要针对构建、调试和开发环境创建不同的 Dockerfile
添加自定义文件
定义容器运行时的用户权限
尽可能避免使用 root 权限运行
定义要对外暴露的端口
定义应用程序的入口点
entrypoint,比较简单的就是直接运行可执行文件,更专业的方法创建一个专门的shell脚本:entrypoint.sh,通过环境变量配置容器的入口点
定义一种配置方式
应用程序如果需要参数,可以使用应用程序特定的配置文件,也可以使用操作系统的环境变量
持久化应用数据
这些数据最好存储到卷或者绑定挂载上,不要将他们保存到容器本身的可写层