Docker之Dockerfile文件制作镜像
Dockerfile简介
dockerfile 是一个文本格式的配置文件, 用户可以使用 Dockerfile 来快速创建自定义的镜像,
另外,使用Dockerfile去构建镜像好比使用pom去构建maven项目一样,有异曲同工之妙
dockerfile基本结构
Dockerfile 由一行行命令语句组成, 并且支持以#开头的注释行,一般而言, Dockerfile 主体内容分为四部分:
基础镜像信息、 维护者信息、 镜像操作指令和容器启动时执行指令。
部分 | 命令 |
---|---|
基础镜像信息 | FROM |
维护者信息 | MAINTAINER |
镜像操作指令 | RUN、(COPY/ADD)、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等 |
容器启动时执行指令 | CMD、ENTRYPOIN |
Dockerfile就是我们用来构建docker镜像的源码。源码不是指变成的源码,里面没有什么条件语句。就是基本的文本指令。
所以说Dockerfile就是纯文本文件,里面包含了一些指令而已。这些指令是dockerfile当中制作时规定的制作指令,也就一二十个
Dockerfile的语法格式
语法格式由两类语句组成:
#注释信息,由#开头
指令及其参数,一行一个指令一般是这样的。一般指令是写成纯大写的,其 本身不区分大小写。约定俗称是使用大写
是顺序执行的指令。整个dockerfile第一个非注释行的第一个指令必须是FROM指令,指的是做当前镜像必须要基于哪个基础镜像来实现。
所以我们的制作过程是基于已有的镜像基础之上来做的,如果没有,我们需要手动去拼凑去做。这样就麻烦大了。
dockerfile做镜像时的工作逻辑:
我们做docker镜像时不一定是当前目录。但是必须要在某个特定目录下进行才行,找一个专门的目录,在这个目录中放进来我们的dockerfile,而且dockerfile文件名首字母必须大写,如果我们想打包很多文件,那么我们必须做好放在专门目录下(不能是这个目录的父目录,可以是它的子目录中的内容,但是不能超出这个路径的边界)。
Dockerfile详解
- from
说明:基于哪个镜像制作
语法:
FROM :[]
此格式是镜像名+版本号,版本号可不写,不写时就是latest版本
FROM @
此格式是镜像名+hash码
例子:
FORM busybox
FORM aaa@qq.com
- maintainer
说明:提供制作镜像本人的详细信息
语法:
MAINTAINER <authtor’s detail>
此格式可以是文本信息,但约定俗成的使用作者名和邮箱地址
例子:
MAINTAINER "ChenWu [email protected] "
- label
说明:为镜像指定各种元数据,仅在docker的新版本中才支持此命令
语法:
LABEL = = =
此格式是键值对形式,并以空格隔开
例子:
LABEL maintainer=“ChenWu [email protected]” app=“service”
- env
说明:定义镜像需要的环境变量
语法:
ENV
此格式只能定义一个变量
ENV =
此格式中如果value中有空格可以用反斜杠 \ 进行转义,也可以对value加引号,另外反斜杠也可以用于续行
例子:
ENV PATH="/home/test"
- workdir
说明:为dockerfile中的run、cmd、entrypoint、copy、add设置工作目录,也就是说在执行命令时会以该目录为当前
语法:
WORKDIR
该指令可以有多个,也可以是相对路径,第二个的路径就会是相对于第一路径,workdir也可以使用ENV定义的变量
例子:
- WORKDIR /var/log
- WORKDIR $PATH
- copy
说明:复制宿主机文件到镜像容器中
语法:
COPY
此格式中src是宿主机路径,必须是build上下文目录中的路径或子路径,不能是父路径,src目录自身是不会被复制的,dest是指镜像容器路径,指定的dest目录如果没有会被自动创建,如果指定多个src或src中用了通配符,dest必须是一个目录,也就是说结尾必须是 / 结尾,建议dest使用绝对路径,否则就使用workdir为相对启始路径
- COPY ["" “”]
当路径中有空格字符时使用此格式
例子:
COPY index.html /data/web/
- add
说明:复制宿主机文件到镜像容器中
例子:
ADD /home/info.sh /home/aa.sh
- volume
说明:镜像容器中会创建一个挂载点目录同时宿主机上也会对应生产一个卷,并且宿主机中的卷会和容器中的卷相互复制
语法:
- VOLUME
- VOLUME [""]
例子:
VLOUME /data/web
- expose
说明:容器打开指定端口与外部通讯,此时宿主机还和容器有映射端口,当docker run 时使用 -P 参数就会映射一个随机端口,没有此参数是不会映射的
语法:
- EXPOSE [/] [/]
此格式可指定多个协议,可为tcp或者udp二者之一,默认是tcp协议
例子:
EXPOSE 8080/tcp 8080/udp
- run
在镜像构建中(docker build)运行的程序命令,此命令关键字只能出现一次,因此多个命令可以用 && 叠加使用
语法:
- RUN
该格式是用shell命令运行的,所以shell是主进程,PID值是1,该命令启动的进程是子进程,PID值不是1,因此当使用docker stop命令停止容器时,子进程是收不到sigterm信号的。
- RUN ["","",""]
该命令不是用shell命令运行的,是直接由内核创建的,所以该命令启动的进程是主进程,PID值是1。所以该命令的参数不能使用变量和通配符操作等,如果要运行shell命令可以使用 RUN ["/bin/bash","-c","","",""] 这种格式。
- cmd
类似RUN命令,都可以用于运行任何命令或程序,他们的区别有以下几点:
RUN运行于镜像文件构建过程中,而CMD是启动一个容器时才执行。
RUN只能写一个,CMD可以写多个,但只有最后一个才会生效
语法
-
CMD
-
CMD ["","",""]
-
CMD ["",""]
前面两种格式和run的两种格式一样,此格式需要结合entry
entrypoint
类似CMD命令,与CMD不同的是容器运行命令docker run不会覆盖entrypoint的命令参数,而CMD命令参数会被docker run命令覆盖,entrypoint命令可以有多个,但只有最后一个才会生效;其实entrypoint命令在docker run中也是可以被覆盖的,加上 --entrypoint 参数明确指出要重写
语法
- ENTRYPOINT
该格式是shell命令运行
- ENTRYPOINT ["","",""]
该格式不是用的shell命令运行。
当CMD和ENTRYPOINT两个相同的命令出现时,CMD的命令会被当做参数在ENTRYPOINT中执行
- user
用于容器运行的用户名或UID,默认情况下是root用户
语法
- USER |
可以为任意数字,但实践中必须是/etc/passwd 中某用户的有效UID,否则 docker run 命令失败
- healthcheck
健康检查,检查容器是否正常运行
语法
- HEALTHCHECK [OPTIONS] CMD
CMD后面跟的就是检查容器健康状态的命令
HEALTHCHECK NONE
关闭健康检查
- shell
定义默认指定的shell命令,不指定时,linux是["/bin/sh","-c"],windows 是[“cmd”,"/S","/C"],该指令一般不用
- stopsignal
当docker stop 命令能停止容器时因为容器接受SIGNAL指令,可以修改SIGNAL名,默认该信号名是15,该命令一般不用
语法
STOPSIGNAL
- arg
定义环境变量,用在在docker build 时,环境变用ARG,在docker run时,环境变量用ENV
语法
ARG ,例如:
ARG aa=“1.14-alpine”
- onbuild
在dockerfile中定义一个触发器,也就是是在docker build时 ,使用ONBUILD命令制作的镜像不会触发该指令,当该镜像作为基础镜像制作成其他镜像时才会触发ONBUILD中的指令
语法
ONBUILD
Docker制作jdk镜像
0.启动虚拟机,进入centos
1.创建文件夹上传jdk的安装包,和在同级目录下编写Dockerfile文件
#创建镜像目录
mkdir –p /ningjie_docker/jdk
#安装lrzsz命令
yum install lrzsz -y
#选择文件进行上传
rz
在这里可以试着使用finalshell工具
# 注意d是大写
touch Dockerfile
2.编写 Dockerfile 文件
#1.指定基础镜像,并且必须是第一条指令
RROM centos:7
#2.指明该镜像的作者和其电子邮件
MAINTAINER zs "aaa@qq.com"
#3.在构建镜像时,指定镜像的工作目录,之后的命令都是基于此工作目录,如果不存在,则会创建目录
WORKDIR /ningjie_docker/jdk
#4.一个复制命令,把jdk安装文件复制到镜像中,语法:ADD <src>... <dest>,注意:jdk*.tar.gz使用的是相对路径
ADD jdk-8u221-linux-x64.tar.gz /ningjie_docker/jdk/
#5.配置环境变量
ENV JAVA_HOME=/ningjie_docker/jdk/jdk1.8.0_221
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH=$JAVA_HOME/bin:$PATH
#容器启动时需要执行的命令
#CMD ["java","-version"]
3.执行Dockerfile文件,初次依赖镜像的时候会下载相应镜像(点不能漏)
docker build -t jdk8:v1.0 .
-
注1:-t jdk8:v1.0 给新构建的镜像取名为 jdk8, 并设定版本为 v1.0
-
注2:注意最后有个点,代表使用当前路径的 Dockerfile 进行构建
4.查看镜像
docker images
5.创建并启动容器
docker run -it jdk8:v1.0 /bin/bash
6.检查是否有问题
java -version
4. dockerfile实践经验
- 精简镜像用途:尽量让每个镜像的用途都比较集中单一,避免构造大而复杂、多功能的镜像
- 选用合适的基础镜像:容器的核心是应用,选择过大的父镜像(如Ubuntu系统镜像)会造成最终生成应用镜像的膝肿,
推荐选用瘦身过的应用镜像或者较为小巧的系统镜像(alpine)
推荐阅读
-
docker中Dockerfile方式建立镜像HelloWorld
-
详解docker中Dockerfile指令创建镜像
-
利用Docker制作Nginx+PHP镜像的步骤详解
-
Docker镜像制作详解介绍
-
docker镜像制作必备技能
-
docker在已有的tomcat镜像上打新的镜像的Dockerfile编写说明介绍
-
Docker学习之基于Dockerfile搭建JAVA Tomcat运行环境的方法
-
Docker中镜像构建文件Dockerfile与相关命令的详细介绍
-
docker官方镜像下载及使用Dockerfile创建镜像的方法
-
Docker 学习笔记 (一)Dockerfile 创建本地镜像