Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
docker build 命令是用于从Dockerfile构建镜像,可以在docker build 命令中使用 -f 参数指向文件系统中任何位置中的Dockerfile文本文件,
如果当前目录下有且仅有一个名为Dockerfile的文件,则可以不使用 -f 指定文件,docker build会自动寻找名为Dockerfile的文件。
Dockerfile一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,“#”为Dockerfile中的注释。
Dockerfile以从上到下的顺序运行Dockerfile的指令。为了指定基本镜像,第一条指令必须是FROM。一个声明以“#”字符开头被视为注释。可以在Dockerfile文件中使用FROM、RUN、CMD、EXPOSE、ENV等指令。
## 格式
FROM
FROM :
FROM :
## 示例
FROM MYSQL:5.7
注: tag或digest是可选的,如果不使用这两个值,会默认使用latest版本的基础镜像。
## 格式
MAINTAINER
## 示例
MAINTAINER zhaowl
MAINTAINER [email protected]
MAINTAINER zhaowl
RUN 用于在镜像容器中执行命令,其有以下两种命令执行方式
## shell格式
RUN <命令行命令>
## exec格式
RUN apk update
## shell格式示例
RUN ["executable", "param1", "param2", ...]
## exec格式示例
RUN ["/etc/execfile", "arg1", "arg2"]
注: RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定 --no-cache参数,如docker build --no-cache
## 格式
ADD ...
## 用于支持包含空格的路径
ADD ["",... ""]
## 示例
## 添加所有以“hom”开头的文件
ADD hom* /mydir/
## ?替代一个单字符,例如:“home.txt”
ADD hom?.txt /mydir/
## 添加“test”到`WORKDIR`/relativeDir/
ADD test relativeDIr/
## 添加“test”到 /absoluteDir/
ADD test /absoluteDir/
## 格式
## 执行可执行文件
CMD ["executable", "param1", "param2"]
## 如果设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数
CMD ["param1", "param2"]
## 执行shell内部命令
CMD command param1 param2
示例
CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc", "--help"]
注: CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
## 格式
## 可执行文件,优先
ENTRYPOINT ["executable", "param1", "param2"]
## shell内部命令
ENTRYPOINT command param1 param2
## 示例
FROM centos:7.2
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
注: ENTRYPOINT与CMD非常相似,不同的是通过 docker run 执行的命令不会覆盖ENTRYPOINT,而 docker run 命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。Dockerfile中只允许一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。
## 格式
LABEL = = ...
## 示例
LABEL version="1.0" description="这是一个Web服务器"
注: 使用LABEL指定元数据时,一条LABEL可以指定一个或多个元数据,指定多个元数据使用空格分割,推荐将所有元数据通过一条LABEL指令指定,避免生成过多的中间镜像。
## 格式
## 设置一个变量。
ENV
## 设置多个变量
ENV = = ...
## 示例
ENV myName zhaowl
ENV myAge 28
ENV myName=zhaowl myAge=28
## 格式
EXPOSE [ ...]
## 示例
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/tcp 11211/upd
注: EXPOSE并不会让容器的端口访问到主机,要使其可访问,需要在 docker run 运行容器时通过 -p 参数来发布这些端口,或通过 -P 参数来发布EXPOSE导出的所有端口。
## 格式
VOLUME ["/path/to/dir"]
## 示例
VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache", "/etc/apache2"]
注: 一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下特点
① 卷可以在容器间共享和重用
② 容器不一定要和其它容器共享卷
③ 修改卷后立即生效
④ 对卷的修改不会对镜像产生影响
⑤ 卷会一直存在,直到没有任何容器在使用它
## 格式
WORKDIR /path/to/workdir
## 示例
## 这时工作目录为/a
WORKDIR /a
## 这时工作目录为/a/b
WORKDIR b
## 这时工作目录为/a/b/c
WORKDIR c
注: 通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用 docker run 运行容器时,可以通过 -w 参数覆盖构建时所设置的工作目录。
后续使用的RUN也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或者两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户,并且可以在之前创建所需要的用户。
## 格式
USER user
USER user:group
USER user:gid
USER uid
USER uid:group
USER uid:gid
## 示例
USER zhaowl
注: 使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过 docker run 运行容器时,可以通过 -u 参数来覆盖所指定的用户。
## 格式
ARG [=]
## 示例
ARG site
ARG build_user=zhaowl
## 格式
ONBUILD [INSTRUCTION]
## 示例
ONBUILD ADD ./app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
注: 当所构建的镜像被用做其它镜像的基础镜像时,该镜像中的触发器将会被钥触发。
## Base images 基础镜像
FROM centos
## MAINTAINER 维护者信息
MAINTAINER zhaowl
## 配置环境变量
ENV MYPATH=/usr/local
## WORKDIR 进入工作目录(相当于cd命令)
WORKDIR $MYPATH
## RUN 执行命令(安装vim和ifconfig命令)
RUN yum -y install vim
RUN yum -y install net-tools
## EXPOSE 暴露交互端口
EXPOSE 80
## CMD 构建容器后执行命令
CMD echo $MYPATH
CMD echo "----- END -----"
CMD /bin/bash
docker build -f dockerfile-centos -t zhaowl/mycentos:1.0 .
docker run -it zhaowl/mycentos:1.0
进入容器后,会直接进入工作目录/usr/local,并且vim和ifconfig命令可以使用,则代表文件编写正确。
apache-tomcat-8.5.71.tar.gz 和 jdk-8u271-linux-x64.tar.gz 以及 readme.txt
## 基础镜像
FROM centos
## 作者
MAINTAINER zhaowl
## 设置基础配置环境变量
ENV MYPATH /usr/local
## 设置工作目录,即登录落脚点
WORKDIR $MYPATH
## 复制readme.txt到工作目录
COPY readme.txt $MYPATH
## 添加tomcat和jdk安装压缩包,并解压
ADD apache-tomcat-8.5.71.tar.gz $MYPATH
ADD jdk-8u271-linux-x64.tar.gz $MYPATH
## 安装vim和ifconfig命令工具
RUN yum -y install vim
RUN yum -y install net-tools
## 配置Java和Tomcat环境变量
ENV JAVA_HOME=$MYPATH/jkd1.8.0_271 CATALINA_HOME=$MYPATH/apache-tomcat-8.5.71 PATH=$PATH:JAVA_HOME/bin:$CATALINA_HOME/bin
## 暴露端口8080
EXPOSE 8080
## 启动容器时启动tomcat,并实时打印日志
ENTRYPOINT $CATALINA_HOME/bin/startup.sh && tail -f $CATALINA_HOME/logs/catalina.out
## 这里没有使用 -f 参数,因为Dockerfile文件为官方命名,docker build会自动寻找
docker build -t zhaowl/mytomcat:1.0 .
docker run -d -p 3443:8080 -v /home/docker/build/tomcat/test:/usr/local/apache-tomcat-8.5.71/webapps/test -v /home/docker/build/tomcat/logs:/usr/local/apache-tomcat-8.5.71/logs zhaowl/mytomcat:1.0
① 在宿主机test目录下新建一个WEB-INF目录,再新建一个index.html文件,并填入自定义内容
## 新建WEB-INF目录
mkdir WEB-INF
## 新建index.html文件
vim index.html
## 添加自定义内容
Hello Tomcat
② 进入WEB-INF目录,并新建一个web.xml文件,并填入基础内容
## 进入WEB-INFO目录
cd WEB-INFO
## 新建web.xml文件
vim web.xml
## 添加基础内容
## 登录DockerHub
docker login -u 用户名 -p 密码
## 发布tomcat:1.0到DockerHub
docker push zhaowl/mytomcat:1.0
## 发布成功
The push refers to repository [docker.io/zhaowl/mytomcat]
1a7c5f1704c5: Pushed
03d7bcbf7f03: Pushed
cd815445598d: Pushed
028fc1c50394: Pushed
a793c92c99d4: Pushed
74ddd0ec08fa: Pushed
1.0: digest: sha256:9483ddbdcb47148075835288c0aebf39872271c3aa9d6a2bcce9b50f64039410 size: 1585
这时我们进入DockerHub的My Profile下的Repositorys中,就会看到我们刚刚发布的镜像了
注: 这里有个坑,之前我们制作镜像时,之所以镜像的名称都会有一个zhaowl/的前缀,这个zhaowl就是我在DockerHub的用户名,就是为了方便发布到DockerHub时使用的,没有这个用户名前缀,镜像是不能发布成功的,会报错:denied: requested access to the resource is denied;那如果忘记给前缀了怎么办?可以用 docker tag 命令来命名并生成一个新的镜像。(别忘记删除旧的镜像 docker rmi)