DockerFile是一个文本格式的配置文件,用户可以使用DockerFile来快速创建自定义的镜像。
Dockerfile分为四部分:基础镜像信息、维护者信息、 镜像操作指令和容器启动时执行指令
比如:
# This Dockerfile uses the ubuntu image
# VERSION 2 - EDITION 1
# Author: docker_user
# Command format: Instruction [arguments / command] ..
# Base image to use, this must be set as the first line
FROM ubuntu:18.04
MAINTAINER docker_user docker_user@email.com
COPY . /app
RUN make /app
CMD python /app/app.py
每条指令创建一层:
Docker镜像由只读层组成,每个只读层代表一个Dockerfile指令。这些层是堆叠的,每个层都是上一层的变化的增量
Docker可以通过读取Dockerfile指令来自动构建镜像
完整的小例子:
#在一个空目录下,新建一个名为 Dockerfile 文件
mkdir /usr/dockerfile -p
vim dockerfile-demo
#编辑 dockerfile
FROM nginx:latest
# 维护者 可以省略
MAINTAINER jourwon jourwon@docker.com
#启动容器
RUN mkdir /usr/share/nginx/html/ -p
RUN echo Hello DockerFile! > /usr/share/nginx/html/demo.html
#构建镜像 . : 根据当前上下文环境构建
docker build -f dockerfile-demo -t jourwon/nginx:v1 .
#运行
docker run --rm -d -it --network host jourwon/nginx:v1
浏览器访问
D ockerfile命令官方文档 常见命令详解:
指定所创建镜像的基础镜像,如果本地不存在,则默认会去Docker Hub下载指定镜像。命令格式如下:
FROM [--platform=<platform>] <image> [AS <name>]
Or
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
Or
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
平时不用这么复杂的,只需如下即可
FROM <image>[:<tag>]
FROM centos:7.6.1810
任何Dockerfile中的第一条指令必须为FROM指令。并且,如果在同 一个Dockerfile中创建多个镜像,可以使用多个FROM指令(每个镜像一 次)。
指定维护者信息,格式为MAINTAINER。可以不写
MAINTAINER jourwon jourwon@docker.com
该信息会写入生成镜像的Author属性域中
容器构建时需要运行的命令
1、RUN
默认将在shell终端中运行命令,即/bin/sh-c
2、RUN [“executable”,“param1”,“param2”]。指令会被解析 为Json数组,因此必须用双引号。exec执行,不会启动shell环境
指定使用其他终端类型可以通过此方式实现,例如
RUN ["/bin/bash","-c","echo hello"]
每条RUN指令将在当前镜像的基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用\来换行
在shell形式中,可以使用\(反斜杠)将一条RUN指令继续到下一行。例如,考虑以下两行:
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
它们在一起等效于以下这一行:
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
要使用’/bin/sh’以外的其他shell ,请使用exec 形式传入所需的shell 。例如:
RUN ["/bin/bash", "-c", "echo hello"]
注意 在JSON格式中,必须转义反斜杠。在Windows中,反斜杠是路径分隔符,这一点尤其重要。由于无效的JSON,以下行否则将被视为shell形式,并以意外的方式失败:
RUN ["c:\windows\system32\tasklist.exe"]
此示例的正确语法为:
RUN ["c:\\windows\\system32\\tasklist.exe"]
CMD指令用来指定启动容器时默认执行的命令。它支持三种格式:
CMD 指令的格式和 RUN 相似:
CMD <命令>
CMD ["可执行文件","参数 1","参数 2"...]
CMD ["参数 1","参数 2"...]
。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体参数复制本地主机的下的内容到镜像中的路径下。目标路径不存在时,会自动创建格式如下:
COPY
src:为Dockerfile所在目录的相对路径、文件或目录dest:镜像中的目标路径,相对和绝对都可以
支持通配符和正则
COPY hom* /mydir/
COPY hom?.txt mydir/
当使用本地目录为源目录时,推荐使用COPY
用来在构建镜像过程中设置环境变量。这个其实就是用一个别名指定一个目录地址,然后后续RUN指令可以通过 $别名 的方式来使用这个目录地址。
格式为ENV或ENV=… ,ENV 指令有两种形式
第一种形式ENV 会将一个变量设置为一个值。第一个空格之后的整个字符串将被视为 -包括空格字符。该值将为其他环境变量解释,因此如果不对引号字符进行转义,则将其删除。
第二种形式ENV = … 允许一次设置多个变量。请注意,第二种形式在语法中使用等号= ,而第一种形式则不使用等号= 。与命令行解析一样,引号和反斜杠可用于在值中包含空格。
例如:
ENV myName="John Doe" myDog=Rex\ The\ Dog \
myCat=fluffy
和
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy
是一样的
ENV 从结果镜像运行容器时,使用设置的环境变量将保留。可以使用查看值docker inspect , 并使用更改它们docker run --env = 。
docker run --env<key>=<value> built_image
将宿主机目录下的文件拷贝到镜像且 ADD
命令会自动处理 URL
和解压 tar
压缩包,格式为
ADD hom* /mydir/
ADD hom?.txt /mydir/
ADD test.txt /absoluteDir/
ADD test.txt relativeDir/
其中可以是Dockerfile所在目录的一个相对路径(文件或目录),也可以是一个URL,还可以是一 个tar文件(如果为tar文件,会自 动解压到路径下)。可以是镜像内的绝对路径,或者相对于工作目录(WORKDIR)的相对路径
与COPY的区别
1、Dockerfile中的COPY指令和ADD指令都可以将主机上的资源复制或加入到容器镜像中,都是在 构建镜像的过程中完成的。
2、COPY指令和ADD指令的区别在于是否支持从远程URL获取资源。COPY指令只能从执行docker build所在的主机上读取资源并复制到镜像中。而ADD指令还支持通过URL从远程服务器读取资源并复制到镜像中。
3、满足同等功能的情况下,推荐使用COPY指令。ADD指令更擅长读取本地tar文件并解压缩
4、当要读取URL远程资源的时候,并不推荐使用ADD指令,而是建议使用RUN指令,在RUN指令 中执行wget 或curl命令
指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的 参数
ENTRYPOINT有两种形式:
ENTRYPOINT ["executable", "param1", "param2"]
,这种执行的是executable param1 param2
ENTRYPOINT command param1 param2
。这中其实执行的是/bin/sh -c command param1 param2
多个ENTRYPOINT 只有最后一条生效
ENTRYPOINT ["echo", "4"]
ENTRYPOINT ["echo", "5"]
ENTRYPOINT ["echo", "6"]
容器数据卷,用于数据保存和持久化工作。
创建一个数据卷挂载点,格式为VOLUME ["/data"]
FROM centos:7.6.1810
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol
RUN echo "hello" > /myvol/greeting
可以从本地主机或其他容器挂载数据卷,一般用来存放数据库和需要保存的数据等
指定在创建容器后,终端默认登陆进来的工作目录,即一个落脚点。
为后续的RUN、CMD和ENTRYPOINT指令配置工作目录格式为WORKDIR /path/to/workdir
可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则 会基于之前命令指定的路径
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
最终的输出pwd命令这Dockerfile 将是/a/b/c
声明镜像内服务所监听的端口格式为EXPOSE[…]
EXPOSE 指令通知Docker 容器在运行时监听指定的网络端口。可以指定端口是侦听TCP 还是
UDP ,如果未指定协议,则默认值为TCP 。
EXPOSE 22 80 8443
默认情况下, EXPOSE 假定为TCP 。还可以指定UDP :
EXPOSE 80/udp
要同时在TCP和UDP上公开,请包括以下两行:
EXPOSE 80/tcp
EXPOSE 80/udp
无论EXPOSE
设置如何,都可以在运行时使用该-p
标志覆盖它们。例如
docker run -p 80:80/tcp
编写完成Dockerfile之后,可以通过docker build命令来创建镜像。
基本的格式为docker build[选项]内容路径,该命令将读取指定路径下(包括子目录)的Dockerfile,并将该路径下的所有内容发送给Docker服务端,由服务端来创建镜像
如果使用非内容路径下的Dockerfile,可以通过-f选项来指定其路径
$ docker build -f /path/to/a/Dockerfile .
要指定生成镜像的标签信息,可以使用-t选项
docker build -t jourwon/ubuntu:v1 .
docker build 最后的 . 号,其实是在指定镜像构建过程中的上下文环境的目录
Docker镜像由一系列层组成。每层代表镜像的Dockerfile中的一条指令。除最后一层外的每一层都是只 读的。考虑以下Dockerfile:
FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py
该Dockerfile包含四个命令,每个命令创建一个层。该 FROM语句首先从ubuntu:18.04镜像创建只读层。
该COPY命令从Docker客户端的当前目录添加一些文件。
该RUN命令使用命令构建您的应用程序make。
最后一层指定在容器中运行什么命令。 运行镜像并生成容器时,可以在基础层之上添加一个新的可写层
(“容器层”)。对运行中的容器所做的所有更改(例如写入新文件,修改现有文件和删除文件)都将写 入此可写容器层。
容器和镜像之间的主要区别是可写顶层。在容器中添加新数据或修改现有数据的所有写操作都存储在此 可写层中。删除容器后,可写层也会被删除。基础镜像保持不变。
因为每个容器都有其自己的可写容器层,并且所有更改都存储在该容器层中,所以多个容器可以共享对 同一基础镜像的访问,但具有自己的数据状态。下图显示了多个共享相同Ubuntu 18.04镜像的容器
查看镜像的分层信息
docker history 镜像ID
磁盘上容器大小
要查看正在运行的容器的大致大小,可以使用以下docker ps -s 命令。有两个不同的列与大小有关。
size :用于每个容器的可写层的数据量(在磁盘上)。
virtual size :容器使用的只读图像数据加上容器的可写层使用的数据量size。多个容器可以共享部分或全部只读图像数据。从同一图像开始的两个容器共享100%的只读数据,而具有不同图像 的两个容器(具有相同的层)共享这些公共层。因此,您不能只对虚拟大小进行总计。这高估了总 磁盘使用量,可能是一笔不小的数目。
我们可以通过Docker仓库来传输我们的镜像,也可以通过文件模式
docker save 镜像ID -o xxxx.tar 或(docker save xxxx > xxxx.tar)
docker load -i xxxx.tar 或docker (docker load < xxxx.tar)
docker diff 容器ID
docker commit 容器ID svendowideit/testimage:version4 # 直接保存容器
docker commit --change='CMD ["apachectl", "-DFOREGROUND"]' -c "EXPOSE 80" 容器ID
svendowideit/testimage:version4 # 将正在运行的容器添加几个层之后再保存】
编写建议:
#在镜像中创建两层
RUN apt-get -y update
RUN apt-get install -y python
#在镜像中创建一层
RUN apt-get -y update && apt-get install -y python
dockerfile-jdk
FROM jourwon/centos/7.6/centos
ENV JAVA_HOME="/apps/jdk"
ENV PATH=${JAVA_HOME}/bin:$PATH
ADD ./jdk-8u251-linux-x64.tar.gz /apps/
RUN ln -s /apps/jdk1.8.0_251 /apps/jdk
ADD ./UnlimitedJCEPolicyJDK8/US_export_policy.jar /apps/jdk/jre/lib/security/
ADD ./UnlimitedJCEPolicyJDK8/local_policy.jar /apps/jdk/jre/lib/security/
ADD ./msyhbd.ttf /apps/jdk/jre/lib/fonts/
ADD ./msyh.ttf /apps/jdk/jre/lib/fonts/
CMD ["/bin/bash"]
构建命令:
#下载jce_policy-8.zip并解压到当前目录
wget http://pkgs-linux.cvimer.com/jdk/1.8/jce_policy-8.zip
unzip jce_policy-8.zip
#下载jdk-8u251-linux-x64.tar.gz、msyh.ttf、msyhbd.ttf
wget http://pkgs-linux.cvimer.com/jdk/1.8/jdk-8u251-linux-x64.tar.gz
wget http://pkgs-linux.cvimer.com/fonts/msyh.ttf
wget http://pkgs-linux.cvimer.com/fonts/msyhbd.ttf
#构建
docker build -f dockerfile-jdk -t jourwon/centos/7.6/jdk/1.8/jdk .
docker volume create test_volume
# 在2个终端窗口启动2个容器
docker run -it --rm -v test_volume:/test nginx:latest /bin/bash
docker run -it --rm -v test_volume:/test nginx:latest /bin/bash
cd /test;
touch a.txt
ls /test
# 在两个容器中我们均可以看到我们创建的文件,这样我们就可以做到了在多个容器之间实现数据共享
挂载在容器/test 目录内创建。Docker 不支持容器内安装点的相对路径。 多个容器可以在同一时间段内使用相同的卷。如果两个容器需要访问共享数据,这将很有用。例如,如果一个容器写入而另一个容器读取数据。 卷名在驱动程序test必须唯一。这意味着我们不能将相同的卷名与两个不同的驱动程序一起使用。 如果们指定了当前test_volume程序上已在使用的卷名,则Docker会假定我们要重用现有卷,并且不会返回错误。如果开始无test_volume 则会创建这个卷
当然除了使用卷,也可以使用将宿主机的文件映射到容器的卷,命令类似,只不过不用提前创建卷,而且数据会映射到宿主机上
docker run -it --rm -v /root/test_volume:/test centos /bin/bash
注意如果宿主机上的目录可以不存在,会在启动容器的时候创建
#
表示注释Docker 在执行 DockerFile 时有以下几个流程:
docker commit
的操作提交一个新的镜像层。从应用软件的角度来看,Dockerfile、Docker镜像和Docker容器分别代表软件的三个阶段:
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/ThinkWon/article/details/120245346
内容来源于网络,如有侵权,请联系作者删除!