Skip to content
DAILY QUOTE

“ ”

DockerFile

1.初始DockerFile

DockerFile是用来构建Docker镜像的构建文件,本质上是一组命令脚本。

通过DockerFile可以生成镜像。镜像是一层一层构建的,DockerFile中每个指令通常都会形成一个镜像层。

1.1编写DockerFile

创建一个DockerFile文件,文件名可以自定义,但建议使用Dockerfile

bash
vim dockerfile1

文件内容:

dockerfile
FROM ubuntu
VOLUME ["volume01","volume02"]
CMD echo "-----end-----"
CMD /bin/bash

说明:

指令作用
FROM ubuntuubuntu作为基础镜像
VOLUME ["volume01","volume02"]声明挂载卷目录
CMD echo "-----end-----"输出测试内容
CMD /bin/bash默认进入bash控制台

注意:CMD可以写多个,但只有最后一个会生效。

1.2构建镜像

bash
docker build -f dockerfile1 -t mystpet/ubuntu .

参数说明:

参数作用
-f dockerfile1指定要读取的DockerFile文件
-t mystpet/ubuntu给构建出的镜像指定名称和标签
.把当前目录作为构建上下文发送给Docker引擎

查看镜像:

bash
ubuntu@Mystpet:~$ docker images
IMAGE                   ID             DISK USAGE   CONTENT SIZE   EXTRA
mystpet/ubuntu:latest   48621b955d22        117MB         29.7MB
mystpet:lastest         d2ca5f8d1213        667MB          214MB

1.3运行自定义镜像

bash
docker run -it 48621b955d22 /bin/bash
ls -l

这个卷和外部一定有一个同步目录。

查看卷挂载信息:

bash
docker inspect 容器id
docker inspect 8f3

测试刚才的文件是否同步到宿主机:

这种方式后续会经常使用,因为实际开发中通常需要构建自己的镜像。

如果构建镜像时没有声明挂载卷,也可以运行容器时手动挂载:

bash
docker run -v 卷名:容器内路径 镜像名

2.数据卷容器

数据卷容器用于让多个容器共享同一份数据,例如多个MySQL容器同步数据。

2.1创建第一个容器

bash
#1.通过自定义镜像创建docker01
docker run -it --name docker01 mystpet/ubuntu:latest

查看容器内容:

bash
root@42db9b1a8946:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var       volume02
boot  etc  lib   media  opt  root  sbin  sys  usr  volume01

不关闭容器退出:

bash
Ctrl+P+Q

2.2创建第二个容器并继承数据卷

bash
ubuntu@Mystpet:~$ docker run -it --name docker02 --volumes-from docker01 mystpet/ubuntu:latest

查看docker02内容:

bash
root@10a8a1e6f3e9:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var       volume02
boot  etc  lib   media  opt  root  sbin  sys  usr  volume01

2.3创建第三个容器继续继承

bash
ubuntu@Mystpet:~$ docker run -it --name docker03 --volumes-from docker01 mystpet/ubuntu:latest

测试:

bash
root@548a6c1962dd:/volume01# ls
docker01.txt

删除docker01后,docker02docker03依旧可以访问共享文件,说明数据没有被删除。

2.4多个MySQL容器数据共享

bash
docker run -d -p 3306:3306 \
  -v /home/mysql/conf:/etc/mysql/conf.d \
  -v /home/mysql/data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=123456 \
  --name mysql01 \
  mysql:5.7

docker run -d -p 3310:3306 \
  -e MYSQL_ROOT_PASSWORD=123456 \
  --name mysql02 \
  --volumes-from mysql01 \
  mysql:5.7

这样可以实现两个MySQL容器之间的数据同步。

结论:

  • 容器之间可以通过数据卷容器传递配置信息和共享数据。
  • 数据卷容器的生命周期会一直持续到没有容器使用为止。
  • 如果数据已经持久化到宿主机,本地数据不会因为容器删除而丢失。

3.DockerFile构建流程

DockerFile是用来构建Docker镜像的文件,是命令参数脚本。

构建步骤:

1.编写DockerFile文件。
2.使用docker build构建镜像。
3.使用docker run运行镜像。
4.使用docker push发布镜像到Docker Hub或阿里云镜像仓库。

查看官方镜像的DockerFile:

点击后可以跳转到对应Dockerfile:

很多官方镜像只像基础包,很多功能都不具备。实际开发中通常需要自己制作镜像。

4.DockerFile构建过程

4.1基础规则

1.每个保留关键字,也就是指令,必须使用大写字母。
2.指令从上到下顺序执行。
3.#表示注释。
4.每个指令都会创建并提交一个新的镜像层。

DockerFile是面向开发的。以后发布项目、制作镜像时,都需要编写DockerFile。

三者关系:

名称作用
DockerFile构建文件,定义镜像构建步骤
DockerImages通过DockerFile构建生成的镜像,是最终发布和运行的产品
Docker容器镜像运行后的实例,用来提供服务

4.2常用指令

dockerfile
FROM        #基础镜像,一切从这里开始构建
LABEL       #镜像元数据,例如作者信息
RUN         #镜像构建时需要运行的命令
ADD         #添加内容,压缩包会自动解压
WORKDIR     #设置镜像工作目录
VOLUME      #设置挂载目录
EXPOSE      #声明容器端口
CMD         #指定容器启动时运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT  #指定容器启动时运行的命令,可以追加命令
ONBUILD     #当构建一个继承当前镜像的DockerFile时触发
COPY        #类似ADD,把文件拷贝到镜像中
ENV         #设置环境变量

说明:新版本Docker更推荐使用LABEL,不建议继续使用MAINTAINER

DockerFile指令说明:

5.基础镜像scratch

dockerfile
FROM scratch
ADD centos-7-x86_64-docker.tar.xz /
LABEL \
  org.label-schema.schema-version="1.0" \
  org.label-schema.name="CentOS Base Image" \
  org.label-schema.vendor="CentOS" \
  org.label-schema.license="GPLv2" \
  org.label-schema.build-date="20200504" \
  org.opencontainers.image.title="CentOS Base Image" \
  org.opencontainers.image.vendor="CentOS" \
  org.opencontainers.image.licenses="GPL-2.0-only" \
  org.opencontainers.image.created="2020-05-04 00:00:00+01:00"
CMD ["/bin/bash"]

Docker Hub中大部分镜像都是从FROM scratch这个基础镜像开始,然后配置需要的软件和环境构建出来的。

6.创建自己的Ubuntu镜像

6.1准备DockerFile目录

bash
#1.在/home/ubuntu下新建dockerfile目录
mkdir dockerfile

#2.在dockerfile目录下新建mydockerfile-ubuntu文件
vim mydockerfile-ubuntu

6.2编写DockerFile配置

dockerfile
FROM ubuntu
LABEL maintainer="Mystpet<1423322347@qq.com>"
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN apt-get update && \
    apt-get install -y vim net-tools
EXPOSE 80
CMD /bin/bash

说明:

  • FROM ubuntu:基础镜像使用Ubuntu。
  • LABEL maintainer:维护者信息。
  • ENV MYPATH /usr/local:设置环境变量。
  • WORKDIR $MYPATH:设置工作目录,进入容器后默认就在这个目录下。
  • RUN apt-get update && apt-get install -y vim net-tools:更新软件源并安装vimnet-tools
  • EXPOSE 80:声明暴露80端口。
  • CMD /bin/bash:容器启动时默认执行bash

6.3构建镜像

bash
docker build -f mydockerfile-ubuntu -t myubuntu:0.1 .

参数说明:

参数作用
-t--tag为构建的镜像指定名称和标签
-f--file指定DockerFile路径

6.4测试运行

bash
docker images
IMAGE                   ID             DISK USAGE   CONTENT SIZE   EXTRA
myubuntu:0.1            bf30232f7cc8        324MB         94.9MB

docker run -it myubuntu:0.1 /bin/bash

root@3f22fd8dd934:/usr/local# pwd
/usr/local

说明:pwd结果和DockerFile中WORKDIR设置的MYPATH一致。

6.5查看镜像构建历史

bash
docker history 镜像id

如果要让CREATED BY列完整显示,可以加上--no-trunc参数。

bash
docker history --no-trunc 镜像:tag

平时拿到一个镜像,可以用docker history 镜像id研究它是怎么构建出来的。

7.CMD和ENTRYPOINT区别

7.1核心区别

dockerfile
CMD         #指定容器启动时运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT  #指定容器启动时运行的命令,可以追加命令
指令特点
CMD提供默认命令,可以被docker run后面的命令替代
ENTRYPOINT提供固定入口,docker run后面的内容会作为参数追加

7.2CMD示例

DockerFile:

dockerfile
FROM ubuntu
CMD ["ls", "-l"]

运行效果:

  • 执行docker run myubuntu时,容器会执行ls -l
  • 执行docker run myubuntu /bin/bash时,CMD会被/bin/bash替代,容器不会执行ls -l

7.3ENTRYPOINT示例

DockerFile:

dockerfile
FROM ubuntu
ENTRYPOINT ["echo", "hello"]

运行效果:

  • 执行docker run myubuntu时,容器会输出hello
  • 执行docker run myubuntu world时,world会作为参数追加到底层命令后面,实际执行的是echo hello world,最终输出hello world

总结:DockerFile中很多指令看起来相似,学习时可以通过对比和测试理解它们的区别。