Dockerfile自定义镜像
docekr学习了解至此,我们都是在使用第三方,也就是远程镜像仓库中的第三方镜像,但是这就会出现一个问题?
问题:镜像是不能修改,只有读的权限,那么在不同的特定环境下,第三方镜像又无法支持我们的需求,这个问题如何解决呢?
所以,就需要我们自定义满足我们需求的镜像,那么我们就必须了解Dockerfile脚本文件
简介
-
Dockerfile构建镜像是以基础镜像为基础的,Dockerfile是一个文本文件,内容是用户编写的一些docker指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
-
Dockerfile就是将自己的程序、文件、环境等构建成自己想要的应用镜像,方便后续部署、启动和维护;通过类似简单编码命令的形式,最终可以构建出属于自己的镜像。
常用指令分类
Dockerfile的基本指令有十三个,分别是:FROM、MAINTAINER、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD
指令类型 | 命令 |
---|---|
基础镜像信息 | FROM |
维护者信息 | MAINTAINER |
镜像操作指令 | RUN、COP、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等 |
容器启动时执行指令 | CMD、ENTRYPOINT |
指令详解
1. FROM 指定基础镜像
- 指定基础镜像 【同时意味着接下来所写的指令将作为镜像的第一层开始】
- 如果不以任何镜像为基础,那么写法为:
FROM scratch
FROM <image>
FROM <image>:<tag>
FROM <image>:<digest>
# <tag>和<digest> 是可选项,如果没有选择,那么默认值为latest
# tag 版本tag标签
# digest
2.MAINTAINER 维护者信息
- 指定作者,姓名&邮箱
MAINTAINER <name>
3. RUN
- 运行指定的命令[如:执行某些动作、安装系统软件、配置系统信息]
- RUN是构件容器时就运行的命令以及提交运行结果
run指令运行命令,有两种格式:
- 直接跟shell命令
- linux系统上默认是
/bin/sh -c
- win系统上默认是
cmd /S /C
- linux系统上默认是
- 类似于函数调用exec
- 可将executable理解成为可执行文件,后面就是两个参数。
- RUN ["可执行文件", "参数1", "参数2"]
语法:
1. RUN <command>
2. RUN ["executable", "param1", "param2"]
示例:
#1. shell 命令格式 向nginx中文首页展示HTML写入‘hello’
RUN echo 'hello ' >/etc/nginx/html/index.html
# 2. exec格式 在新镜像中使用yum的方式安装nginx
RUN ["yum","install","nginx"]
注意:
- 多行命令不要写多个RUN,Dockerfile中每一个指令都会建立一层
- RUN 指令的行数代表镜像的层数,一个镜像中它的文件层数是有最大值的,而且层数太多增加了构件部署的时间
- RUN书写时的换行符是
\
4. CMD
- 容器启动时要运行的命令
- CMD是容器启动时执行的命令,在构件时并不运行,构件时紧紧指定了这个命令到底是个什么样子
CMD 有三种写法:
# 1. exec 格式:CMD ["可执行文件", "参数1", "参数2"...]
CMD ["executable","param1","param2"]
# 例如:
CMD [ "sh", "-c", "echo $HOME" ]
# 2. exec
CMD ["param1","param2"]
# 例如:
CMD ["/bin/bash"]
# 3. shell格式
CMD command param1 param2
# 例如:
CMD /bin/bash
# 第三种比较好理解了,就时shell这种执行方式和写法
# 第一种和第二种其实都是可执行文件加上参数的形式
注意:
-
exec
格式的情况下,参数必须用双引号【原因:docker解析的是一个JSON array】 - CMD在Dockerfile中只能出现一次,如果出现多个,那么只有最后一个会有效,其作用是在启动容器的时候提供一个默认的命令项。如果用户执行docker run的时候提供了命令项,就会覆盖掉这个命令,没提供就会使用构建时的命令。
5. LABEL 标签
- 为镜像指定标签
语法:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
# Dockerfile种可以有多个LABEL标签
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
注意:
- LABEL会继承基础镜像种的LABEL,如遇到key相同,则值覆盖
6. MAINTAINER 作者信息
- 指定作者和邮箱
MAINTAINER <name> <email>
# 例如 :
MAINTAINER autor_yuchang 8888888@qq.com
7. EXPOSE 暴露端口
- 设置容器对外映射的容器端口号
EXPOSE <端口1> [<端口2>...]
EXPOSE 8081 其实等价于 docker run -p 8081 当需要把8081端口映射到宿主机中的某个端口(如8888)以便外界访问时,则可以用docker run -p 8888:8081
8. ENV 环境变量
- 设置环境变量
- 在容器内被脚本或者程序调用,容器运行的时候这个变量也会保留
语法:
# 单个环境变量
ENV <key> <value>
# 多个环境变量
ENV <key>=<value> ...
# 例如: 设置一个环境变量JAVA_HOME
ENV JAVA_HOME /opt/jdk
ENV PATH $PATH:$JAVA_HOME/bin
注意:
- 具有传递性,也就是当前镜像被用作其它镜像的基础镜像时,新镜像会拥有当前这个基础镜像所有的环境变量
- ENV定义的环境变量,可以在dockerfile被后面的所有指令(CMD除外)中使用,但不能被docker run 的命令参数引用
# 具有传递性
ENV tomcat_home_name tomcat_7
RUN mkdir $tomcat_home_name
9. ADD 复制
- 复制命令,把文件复制到镜像中
- 与COPY指令一样
语法:
# <src>可以是一个本地文件或者是一个本地压缩文件,还可以是一个url[<src>写成一个url,那么ADD就类似于wget命令]
# <dest>路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径
ADD <src>... <dest>
ADD ["<src>",... "<dest>"]
# 例如:
ADD test relativeDir/
ADD test /relativeDir
ADD http://example.com/foobar /
# 注意:尽量不要把<scr>写成一个文件夹,如果<src>是一个文件夹了,复制整个目录的内容,包括文件系统元数据
10. COPY
- 复制命令
- 与add命令相同
语法:
COPY <src>... <dest>
COPY ["<src>",... "<dest>"]
注意:
- COPY的
<src>
只能是本地文件,其他用法一致
11. ENTRYPOINT
- 启动时 的默认命令【与CMD有些类似】
语法:
# entrypoint 基本语法分为两种
# 1. 指令后直接跟shell命令
ENTRYPOINT command param1 param2
# 2. 可执行文件加参数
ENTRYPOINT ["executable", "param1", "param2"]
12. VOLUME
- 实现挂载功能【将内地文件夹或者其他容器中得文件夹挂在到这个容器中】
- 数据持久化,容器数据共享
语法:
VOLUME ["/data"]
# ["/data"]可以是一个JsonArray ,也可以是多个值
VOLUME ["/var/log/"]
VOLUME /var/log
VOLUME /var/log /var/db
# 也可以用过docker run -v来把匿名挂载点挂载都宿主机器上的某个目录
docker run -d -v 容器目录:本地目录
13. USER
- 设置启动容器的用户【可以是用户名或用户uid】
语法:
#注意:如果设置了容器以daemon用户去运行,那么RUN, CMD 和 ENTRYPOINT 都会以这个用户去运行
USER daemo
USER UID
14. WORKDIR
- 设置工作目录【用于目录的切换,如果目录不存在则会直接创建一个新目录】
语法:
# 注意:WORKDIR命令可以有多次出现
WORKDIR /path/to/workdir
# WORKDIR也可以解析环境变量
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
# pwd的执行结果是/path/$DIRNAME
15. ONBUILD
- 用于配置当前所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令
语法:
ONBUILD [INSTRUCTION]
16. ENV
- 设置容器的环境变量【
key=value
的形式存在,在容器内被脚本或者程序调用,容器运行的时候这个变量也会保留】
语法:
# 设置一个参数
ENV <key> <value>
#也可以设置多个参数
ENV <key1>=<value1> <key2>=<value2>...
# 例如:设置一个环境变量JAVA_HOME
ENV JAVA_HOME /opt/jdk
ENV PATH $PATH:$JAVA_HOME/bin
注意:
- 具有传递性,也就是当前镜像被用作其它镜像的基础镜像时,新镜像会拥有当前这个基础镜像所有的环境变量
- ENV定义的环境变量,可以在dockerfile被后面的所有指令(CMD除外)中使用,但不能被docker run 的命令参数引用
- 除了ENV之外,docker run -e 也可以设置环境变量传入容器内。
17. HEALTHCHECK
- 容器健康状况检查命令
语法:
# 在容器内部运行一个命令来检查容器的健康状况
HEALTHCHECK [OPTIONS] CMD command
# 在基础镜像中取消健康检查命令
HEALTHCHECK NONE
[OPTIONS]的选项支持以下三中选项:
- --interval=DURATION 两次检查默认的时间间隔为30秒
- --timeout=DURATION 健康检查命令运行超时时长,默认30秒
- --retries=N 当连续失败指定次数后,则容器被认为是不健康的,状态为unhealthy,默认次数是3
注意:
- HEALTHCHECK命令只能出现一次,如果出现了多次,只有最后一个生效。
- CMD后边的命令的返回值决定了本次健康检查是否成功
0: success - 表示容器是健康的
1: unhealthy - 表示容器已经不能工作了
2: reserved - 保留值
# 例如:
例子:
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1
# 健康检查命令是:curl -f http://localhost/ || exit 1
# 两次检查的间隔时间是5秒,命令超时时间为3秒
Dockerfile的编写和实战
了解完,dockerfile的基本命令,我们尝试编写一个dockerfile文件
编写dockerfile
- 使用idea编写,下载docker插件
- 在centos系统上安装一个nginx
FROM centos
MAINTAINER test123 123456789@qq.com
RUN ping -c 1 www.baidu.com
RUN yum -y install gcc make pcre-devel zlib-devel tar zlib
ADD nginx-1.18.0.tar.gz /usr/src
RUN cd /usr/src/nginx-1.18.0 \
&& mkdir /usr/local/nginx \
&& ./configure --prefix=/usr/local/nginx && make &&make install \
&& ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/ \
&& nginx
RUN rm -rf /usr/src/nginx-1.18.0
EXPOSE 80
CMD ["nginx","-g","daemon off;"]
并把已经下载好的nginx包和编写好的dockerfile文件上传到服务器中,在同一文件夹
- 用Dockerfile构建镜像
docker build 命令
[root@bogon data]# docker build --help
Usage: docker build [OPTIONS] PATH | URL | -
Build an image from a Dockerfile
Options:
--add-host list Add a custom host-to-IP mapping (host:ip)
--build-arg list Set build-time variables
--cache-from strings Images to consider as cache sources
--cgroup-parent string Optional parent cgroup for the container
--compress Compress the build context using gzip
--cpu-period int Limit the CPU CFS (Completely Fair Scheduler) period
--cpu-quota int Limit the CPU CFS (Completely Fair Scheduler) quota
-c, --cpu-shares int CPU shares (relative weight)
--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
--disable-content-trust Skip image verification (default true)
-f, --file string Name of the Dockerfile (Default is 'PATH/Dockerfile')
--force-rm Always remove intermediate containers
--iidfile string Write the image ID to the file
--isolation string Container isolation technology
--label list Set metadata for an image
-m, --memory bytes Memory limit
--memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap
--network string Set the networking mode for the RUN instructions during build (default "default")
--no-cache Do not use cache when building the image
--pull Always attempt to pull a newer version of the image
-q, --quiet Suppress the build output and print image ID on success
--rm Remove intermediate containers after a successful build (default true)
--security-opt strings Security options
--shm-size bytes Size of /dev/shm
-t, --tag list Name and optionally a tag in the 'name:tag' format
--target string Set the target build stage to build.
--ulimit ulimit Ulimit options (default [])
[root@bogon data]#
# 常用的指令
--build-arg=[] # 设置镜像创建时的变量
-f # 指定要使用的dockerfile 的路径【当Dockerfile和当前执行命令的目录不在同一个时,可以指定Dockerfile】
--force-rm # 设置镜像过程中删除中间容器
--rm # 设置镜像成功后删除中间容器
--tag,-t # 镜像的名字及标签,通常name:tag或者name格式
开始构建,执行命令
docker build -t mynginx:1.18.0 .
# -t 镜像的名字及标签
# 最后有一个‘.‘不要忘记,代表当前目录
我们可以看到,执行过程中,根据我们编写的指令,有步骤
- 查看并运行自定义镜像
可以看到,通过docker images 命令可以看到我们构建的镜像已经存在于本地
启动镜像:
# 1. 先启动centos
docker run -d -i -t -p 8081:80 30178ab47eaf
# 启动容器,不可以加/bin/bash 会把dockerfilr中的CMD命令覆盖导致无法启动80端口
# 产生问题: docker curl: (56) Recv failure: Connection reset by peer
# 解决:启动命令不可以加/bin/bash参数
提交本地镜像到远程
- docker login登录
docker login # 登录远程仓库
- 将容器提交为新镜像
docker commit 容器id\容器名 新的镜像名字:版本
# 注意:镜像名必须为 xxx/name xxx为你dockerhub上的用户名base为仓库名,不然会后面push会失败
docker commit 5615647e67a1 casainurbania/base:v1.0
- 推送到远程仓库
docker push casainurbania/base:v1.0
MYSQL5.6案例dockerfile分析
相关Docker文章推荐
参考文章:
Dockerfile命令详解(超全版本)[https://www.cnblogs.com/dazhoushuoceshi/p/7066041.html]
如何用Dockerfile构建镜像 [https://www.cnblogs.com/momoyan/p/12437312.html]