总结这几天使用Dockerfile和docker-Compose的经验

dockerfile

基本知识点

  • 镜像的构建步骤按照dockerfile里的指令顺序来构建。
  • docker镜像是分层的,通过dockerfile构建镜像时,每一句指令就是一层,每执行一句就填加一层,最底层则是基础镜像,即from指令所指定的镜像。
  • docker的容器即是在镜像之上加上一个可以读写的临时层
  • 构建过程中的删除操作只在所在的指令语句的那一层中起作用。比如有两句RUN指令:前一个是安装了某个软件或添加了每个文件,即执行了对镜像来说增大体积的操作;后一个则是卸载这个软件的下载缓存或删除对应的目标文件,既执行了对镜像来说的减少体积的操作。那么,镜像真的会减去这一部分的体积吗?不,并不会,在docker镜像构建过程中,它是一层一层往上叠的,或者说,新的层会继承旧的层,所以,在旧的层里加进镜像里的东西,哪怕在后面的层执行了删除操作也并不会真正的删除,依旧会存留在镜像内。所以要缩减镜像体积的话,首先要选一个符合要求的、最小的基础镜像,然后构建过程中每一次安装软件都要注意在同一个RUN操作中同时执行清除缓存等操作。
  • docker的规范规定,dockerfile的文件名必须是dockerfile,但dockerfile这两个单词的首字母不区分大小写。
  • 镜像名称的表现形式有两种:一种是只有镜像名称——image[:tag](如,nginxnignx:14.0),在该情况下代表着如果本地不存在该名称的镜像的话,docker会从docker hub查询并下载;另一种是IP/域名+镜像名:{ip/domain}[:port][/folder]/image[:tag](如,127.0.0.1:8081/floder1/dockerImage:1.2.3www.demo.com:8081/floder1/dockerImage:1.2.3),在该情况下代表着如果本地不存在指定的镜像的话将会从指定的地址下载对应的镜像,而且如果下载的镜像如果是私有镜像的话还需要先在终端执行docker login {ip/domain}[:port]进行登录后才可以下载。

指令参数的作用

  • FROM:该参数所在的指令必须要放在dockerfile文件的第一行,用于指定dockerfile所构建的镜像的基础镜像是什么,该参数以镜像名称作为值
  • RUN:该参数表示在构建过程中需要执行的bash命令。如 RUN: uname -a
  • LABEL:用于自定义镜像的元数据,如LABEL author="AlexC"定义了author为AlexC
  • ARG:定义了构建镜像时的环境变量。如ARG a=1,那么如果我在后面的指令中有用到变量a的值的地方的话,我只需要使用美元符+变量名,即$a就可以了,如WORKDIR /root/$a,这里的意思就是工作目录设定在WORKDIR/root/1
  • COPY:用于复制外部文件进镜像。对外部文件支持相对路径和绝对路径。使用格式为COPY {原文件路径}+空格+{目标文件路径},如COPY ROOT.war /home的意思就是把与dockerfile同级的ROOT.war放进镜像内部的/home目录下。

dockerfile示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 本镜像的基础镜像
FROM tomcat:8-slim
# 记录维护者联系方式到镜像的元数据
LABEL maintainer="alexcdever@gmail.com"
# 设置工作目录
WORKDIR /root
# 定义构建变量,以下变量只在构建镜像过程中起作用,不会写入到镜像中的操作系统里
ARG tomcat="/usr/local/tomcat"
ARG web="${tomcat}/webapps"
ARG log="${tomcat}/logs"
ARG workspace="/home/ProjectWorkspace"
# 表示以root用户操作镜像内的系统
USER root

# 执行更新系统的操作
RUN apt update -y \
&& apt upgrade -y

# 安装软件
RUN apt install -y imagemagick

RUN rm -rf ${web}/*

# 复制与dockerfile文件在同一目录下的一个叫index.html的文件到镜像内的root目录下
COPY ROOT.rar /root/
RUN mkdir ${web}/ROOT \
&& unzip /root/ROOT.war -d ${web}/ROOT/

docker-compose

基本知识点

  • docker-compose是一个简单的docker镜像编排工具,其配置文件名称一般默认为为docker-compose.yml,docker-compose将会根据该配置文件里的设置构建出单个或多个docker容器以及其他和容器相关的东西并按照配置项将不同容器联系起来。

配置项

​ 用过yaml做配置文件的应该都知道.yml文件的写法其实和json的格式是类似的,都是键值对。在docker-compose的配置文件里有两大配置项是必要的,他们分别是serviceVERSION

  • VERSION:该属性的用法是用于指定docker-compose在根据配置文件执行时编排操作时使用的API版本,现在最新版是3,所以一般来说该标签的写法都是VERSION: "3"
  • services:按我的了解,对于docker来说,一个容器相当于一个服务,所以在services下的都是服务。每一个容器都需要指定一个镜像用于生成容器。
  • NETWORK:表示网段,其下的二级配置项表示不同的隔离网络,每个网络可以使用driver属性定义网络的连接模式。模式有三种,分别是桥接模式bridge、宿主模式host和容器模式container [container name]
  • VOLUMES:表示数据卷,其下二级配置项表示不同的数据卷。当声明一个空数据卷时(即只有一个数据卷名字且不存在任何属性),该数据卷会根据docker自身的缺省值在/var/lib/docker/volumes/{hash值}/_data这个路径是我在Mac OS 10.11.6里查到的,不保证其他版本和其他系统也是这个路径)里存放被挂载映射的数据。

docker-compose.yml示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 声明docker-compose执行编排时使用的api版本
version: '3'

networks:
# 声明了一个名字叫app的隔离网络,该网络的连接模式为桥接模式
app:
driver: bridge

volumes:
# 声明了一个名字叫db的数据卷,且不做设置,即一切设置都是用docker的缺省值
db:
services:
# 定义了一个,名字叫mysql的服务
mysql:
# 声明该服务所使用的镜像是来自于docker hub的mysql:latest镜像
image: mysql
# 声明本次启动的基于mysql:latest镜像的容器的名字为mysql
container_name: mysql
# 为容器提权,避免容器在启动时遇到权限不足导致启动失败的情况
privileged: true
# 表示该容器会随着宿主机的重启而重启
restart: always
# 表示对外暴露的端口,这里是要将容器内的3306端口映射到宿主机的3306端口,冒号左边是宿主机的端口,右边是容器内的端口
ports:
- "3306:3306"
# 这里表示本容器的网络使用的是名字为app的网段
networks:
- app
# 这里表示向其它同样在相同网段内的其他容器暴露自己的3306端口,其他容器可以通过3306端口访问本容器的3306端口
expose:
- "3306"
# 这里表示将容器内的/var/lib/mysql目录与名为db的数据卷映射
volumes:
- "db:/var/lib/mysql"
# 这里表示本service依赖于一个叫abc的服务。在docker-compose中,service的启动顺序越是被其它service所依赖,那么这个service的启动优先级越高,但docker-compose的启动并不是阻塞同步的,而是只是排好启动顺序后按顺序发送启动指令,所以当一个叫“甲”的服务启动时间长而未启动完成时,依赖于“甲”的服务“乙”需要调用“甲”时,“乙就会报错”。所以请注意这一点。
depend_on:
- "abc"
AlexC wechat
博客与公众号同步发文,欢迎关注
感谢你的支持