DockerFile
1.初始DockerFile
DockerFile是用来构建Docker镜像的构建文件,本质上是一组命令脚本。
通过DockerFile可以生成镜像。镜像是一层一层构建的,DockerFile中每个指令通常都会形成一个镜像层。
1.1编写DockerFile
创建一个DockerFile文件,文件名可以自定义,但建议使用Dockerfile。
vim dockerfile1文件内容:
FROM ubuntu
VOLUME ["volume01","volume02"]
CMD echo "-----end-----"
CMD /bin/bash说明:
| 指令 | 作用 |
|---|---|
FROM ubuntu | 以ubuntu作为基础镜像 |
VOLUME ["volume01","volume02"] | 声明挂载卷目录 |
CMD echo "-----end-----" | 输出测试内容 |
CMD /bin/bash | 默认进入bash控制台 |
注意:CMD可以写多个,但只有最后一个会生效。
1.2构建镜像
docker build -f dockerfile1 -t mystpet/ubuntu .参数说明:
| 参数 | 作用 |
|---|---|
-f dockerfile1 | 指定要读取的DockerFile文件 |
-t mystpet/ubuntu | 给构建出的镜像指定名称和标签 |
. | 把当前目录作为构建上下文发送给Docker引擎 |
查看镜像:
ubuntu@Mystpet:~$ docker images
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
mystpet/ubuntu:latest 48621b955d22 117MB 29.7MB
mystpet:lastest d2ca5f8d1213 667MB 214MB1.3运行自定义镜像
docker run -it 48621b955d22 /bin/bash
ls -l
这个卷和外部一定有一个同步目录。

查看卷挂载信息:
docker inspect 容器id
docker inspect 8f3
测试刚才的文件是否同步到宿主机:


这种方式后续会经常使用,因为实际开发中通常需要构建自己的镜像。
如果构建镜像时没有声明挂载卷,也可以运行容器时手动挂载:
docker run -v 卷名:容器内路径 镜像名2.数据卷容器
数据卷容器用于让多个容器共享同一份数据,例如多个MySQL容器同步数据。

2.1创建第一个容器
#1.通过自定义镜像创建docker01
docker run -it --name docker01 mystpet/ubuntu:latest查看容器内容:
root@42db9b1a8946:/# ls
bin dev home lib64 mnt proc run srv tmp var volume02
boot etc lib media opt root sbin sys usr volume01不关闭容器退出:
Ctrl+P+Q2.2创建第二个容器并继承数据卷
ubuntu@Mystpet:~$ docker run -it --name docker02 --volumes-from docker01 mystpet/ubuntu:latest查看docker02内容:
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创建第三个容器继续继承
ubuntu@Mystpet:~$ docker run -it --name docker03 --volumes-from docker01 mystpet/ubuntu:latest测试:
root@548a6c1962dd:/volume01# ls
docker01.txt删除docker01后,docker02和docker03依旧可以访问共享文件,说明数据没有被删除。

2.4多个MySQL容器数据共享
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常用指令
FROM #基础镜像,一切从这里开始构建
LABEL #镜像元数据,例如作者信息
RUN #镜像构建时需要运行的命令
ADD #添加内容,压缩包会自动解压
WORKDIR #设置镜像工作目录
VOLUME #设置挂载目录
EXPOSE #声明容器端口
CMD #指定容器启动时运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定容器启动时运行的命令,可以追加命令
ONBUILD #当构建一个继承当前镜像的DockerFile时触发
COPY #类似ADD,把文件拷贝到镜像中
ENV #设置环境变量说明:新版本Docker更推荐使用LABEL,不建议继续使用MAINTAINER。
DockerFile指令说明:

5.基础镜像scratch
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目录
#1.在/home/ubuntu下新建dockerfile目录
mkdir dockerfile
#2.在dockerfile目录下新建mydockerfile-ubuntu文件
vim mydockerfile-ubuntu6.2编写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:更新软件源并安装vim和net-tools。EXPOSE 80:声明暴露80端口。CMD /bin/bash:容器启动时默认执行bash。
6.3构建镜像
docker build -f mydockerfile-ubuntu -t myubuntu:0.1 .参数说明:
| 参数 | 作用 |
|---|---|
-t或--tag | 为构建的镜像指定名称和标签 |
-f或--file | 指定DockerFile路径 |

6.4测试运行
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查看镜像构建历史
docker history 镜像id如果要让CREATED BY列完整显示,可以加上--no-trunc参数。
docker history --no-trunc 镜像:tag
平时拿到一个镜像,可以用docker history 镜像id研究它是怎么构建出来的。
7.CMD和ENTRYPOINT区别
7.1核心区别
CMD #指定容器启动时运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定容器启动时运行的命令,可以追加命令| 指令 | 特点 |
|---|---|
CMD | 提供默认命令,可以被docker run后面的命令替代 |
ENTRYPOINT | 提供固定入口,docker run后面的内容会作为参数追加 |
7.2CMD示例
DockerFile:
FROM ubuntu
CMD ["ls", "-l"]运行效果:
- 执行
docker run myubuntu时,容器会执行ls -l。 - 执行
docker run myubuntu /bin/bash时,CMD会被/bin/bash替代,容器不会执行ls -l。
7.3ENTRYPOINT示例
DockerFile:
FROM ubuntu
ENTRYPOINT ["echo", "hello"]运行效果:
- 执行
docker run myubuntu时,容器会输出hello。 - 执行
docker run myubuntu world时,world会作为参数追加到底层命令后面,实际执行的是echo hello world,最终输出hello world。
总结:DockerFile中很多指令看起来相似,学习时可以通过对比和测试理解它们的区别。