Dockerfile自定义镜像

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指令运行命令,有两种格式:

  1. 直接跟shell命令
    • linux系统上默认是 /bin/sh -c
    • win系统上默认是cmd /S /C
  2. 类似于函数调用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"]

注意:

  1. 多行命令不要写多个RUN,Dockerfile中每一个指令都会建立一层
  2. RUN 指令的行数代表镜像的层数,一个镜像中它的文件层数是有最大值的,而且层数太多增加了构件部署的时间
  3. 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这种执行方式和写法
# 第一种和第二种其实都是可执行文件加上参数的形式

注意:

  1. exec格式的情况下,参数必须用双引号【原因:docker解析的是一个JSON array】
  2. CMD在Dockerfile中只能出现一次,如果出现多个,那么只有最后一个会有效,其作用是在启动容器的时候提供一个默认的命令项。如果用户执行docker run的时候提供了命令项,就会覆盖掉这个命令,没提供就会使用构建时的命令。

5. LABEL 标签

  • 为镜像指定标签

语法:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

# Dockerfile种可以有多个LABEL标签
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"

注意:

  1. 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

注意:

  1. 具有传递性,也就是当前镜像被用作其它镜像的基础镜像时,新镜像会拥有当前这个基础镜像所有的环境变量
  2. 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>"]

注意:

  1. COPY的<src>只能是本地文件,其他用法一致

11. ENTRYPOINT

  • 启动时 的默认命令【与CMD有些类似】

语法:

# entrypoint 基本语法分为两种
# 1. 指令后直接跟shell命令
ENTRYPOINT command param1 param2
# 2. 可执行文件加参数
ENTRYPOINT ["executable", "param1", "param2"]

ENTRYPOINT & CMD比较

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

注意:

  1. 具有传递性,也就是当前镜像被用作其它镜像的基础镜像时,新镜像会拥有当前这个基础镜像所有的环境变量
  2. ENV定义的环境变量,可以在dockerfile被后面的所有指令(CMD除外)中使用,但不能被docker run 的命令参数引用
  3. 除了ENV之外,docker run -e 也可以设置环境变量传入容器内。

17. HEALTHCHECK

  • 容器健康状况检查命令

语法:

# 在容器内部运行一个命令来检查容器的健康状况
HEALTHCHECK [OPTIONS] CMD command
# 在基础镜像中取消健康检查命令
HEALTHCHECK NONE

[OPTIONS]的选项支持以下三中选项:

  • --interval=DURATION 两次检查默认的时间间隔为30秒
  • --timeout=DURATION 健康检查命令运行超时时长,默认30秒
  • --retries=N 当连续失败指定次数后,则容器被认为是不健康的,状态为unhealthy,默认次数是3

注意:

  1. HEALTHCHECK命令只能出现一次,如果出现了多次,只有最后一个生效。
  2. 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

  1. 使用idea编写,下载docker插件

image-20211124103405250

image-20211124103533853

  1. 在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文件上传到服务器中,在同一文件夹

  1. 用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 	镜像的名字及标签 
# 最后有一个‘.‘不要忘记,代表当前目录

我们可以看到,执行过程中,根据我们编写的指令,有步骤

image-20211124134334764

  1. 查看并运行自定义镜像

image-20211124134446292

可以看到,通过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参数

image-20211124142650365

提交本地镜像到远程

  1. docker login登录
docker login # 登录远程仓库
  1. 将容器提交为新镜像
docker commit 容器id\容器名 新的镜像名字:版本

# 注意:镜像名必须为 xxx/name   xxx为你dockerhub上的用户名base为仓库名,不然会后面push会失败

docker commit 5615647e67a1 casainurbania/base:v1.0
  1. 推送到远程仓库
docker push casainurbania/base:v1.0

MYSQL5.6案例dockerfile分析

推荐: MYSQL5.6案例dockerfile分析


相关Docker文章推荐

Docker文件系统 & 数据卷

Docker 安装及基本命令

Docker 部署nginx/tomcat/ES+kibana

Docker网络

Docker C/S架构

Dockerfile自定义镜像

参考文章:

Dockerfile命令详解(超全版本)[https://www.cnblogs.com/dazhoushuoceshi/p/7066041.html]
如何用Dockerfile构建镜像 [https://www.cnblogs.com/momoyan/p/12437312.html]
posted @ 2021-11-24 14:54  Mr*宇晨  阅读(605)  评论(0编辑  收藏  举报