0x00 引言
Docker是一个开源的应用容器引擎,可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,类似于一种轻型的虚拟机。
- Docker架构由三个部分组成:
- 仓库: 一个仓库能存放大量镜像
- 镜像: 相当于是一个root文件系统
- 容器: 一个镜像运行时的实体,可以被创建、启动、停止、删除、暂停。镜像与容器的关系就像是类和实例
0x01 Docker基础知识
1 | 1 镜像分层 |
1、镜像分层
单个Docker镜像能被实例化为多个容器,那么基于同一镜像的多个容器同时运行时是共用一个镜像,还是每个容器各复制一份镜像呢?
为了回答上述问题,首先我们来看一个用于构建镜像的基础Dockerfile:
1 | FROM ubuntu:18.04 # 基础镜像 |
一个docker镜像由多个可读的镜像层组成,然后运行的容器会在这个docker的镜像上面多加一层可写的容器层,任何的对文件的更改都只存在此容器层。因此任何对容器的操作均不会影响到镜像。因此,基于同一镜像的多个可读写容器同时运行时是共用一个只读镜像。
2、镜像存储
由上一节可知,容器 = 镜像 + 读写层。那么这些镜像与容器是如何在磁盘中存储的呢?
2.1、写时复制与用时分配
- 目前所有的存储驱动都使用了CoW技术(copy-on-write),即写时复制与用时分配:
- 写时复制: 只有容器要对镜像中的文件进行修改时,才会将镜像文件副本拷贝到自己的文件系统进行修改;
- 用时分配: 启动一个容器,并不会为这个容器预分配一些磁盘空间,而是当有新文件(不存在于镜像中的文件)写入时,才按需分配新空间。
2.2、存储驱动
- 常见的存储驱动为以下几个:
- AUFS - AnotherUnionFS,是一种Union FS,文件级的存储驱动。镜像在存储时被分为多层;
- OverlayFS - 是一种Union FS,文件级的存储驱动(Linux内核3.18后支持的)。镜像在存储时为单层;
- Devicemapper - 块级的存储驱动(Linux内核2.6.9后支持的)。所有的操作都是直接对块进行操作,而不是文件。
0x02 Docker基础用法
1 | 1 仓库 |
1、仓库
1 | # 登陆Docker Hub注册账号 https://hub.docker.com |
2、镜像
1 | # 列出镜像列表 |
3、容器
1 | # 新建容器 |
4、特殊指令
1 | # 获取容器/镜像的元数据 |
0x03 Dockerfile构建镜像
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
1 | 1 命令摘要 |
1、命令摘要
- FROM - 构建镜像基于哪个镜像
- MAINTAINER - 镜像维护者姓名或邮箱地址
- RUN - 构建镜像时运行的指令
- CMD - 运行容器时执行的shell环境
- VOLUME - 指定容器挂载点到宿主机自动生成的目录或其他容器
- USER - 为RUN、CMD、和 ENTRYPOINT 执行命令指定运行用户
- WORKDIR - 为 RUN、CMD、ENTRYPOINT、COPY 和 ADD 设置工作目录,就是切换目录
- HEALTHCHECH - 健康检查
- ARG - 构建时指定的一些参数
- EXPOSE - 声明容器的服务端口(仅仅是声明)
- ENV - 设置容器环境变量
- ADD - 拷贝文件或目录到容器中,如果是URL或压缩包便会自动下载或自动解压
- COPY - 拷贝文件或目录到容器中,跟ADD类似,但不具备自动下载或解压的功能
- ENTRYPOINT - 运行容器时执行的shell命令
2、Dockerfile实例
1 | FROM ubuntu:latest |
注意1: CMD或者ENTRYPOINT在容器运行后会执行命令,程序运行结束,容器也就结束。并且上述两个命令如果由多个,则只有最后一个起效
注意2: 如果需要使用CMD或者ENTRYPOINT在容器运行后开启多个服务,需要用其运行一个脚本,在脚本中使用’&’方式后台启动多个服务。
注意3: 如果希望CMD或者ENTRYPOINT脚本在运行完毕后不结束容器,则可在最后添加’/bin/bash’语句
3、镜像构建
1 | # 进入Dockerfile所在目录 |
4、多阶段构建
Docker 17.05版本以后,支持了多阶段构建,允许一个Dockerfile 中出现多个 FROM 指令。
多个 FROM 指令时,最后生成的镜像,仍以最后一条 FROM 为准,之前的 FROM 会被抛弃。但是在后面的 FROM 指令中, 能够将前置阶段中的文件拷贝到后边的阶段中,这就是多阶段构建的最大意义。使用示例:
1 | # 编译阶段 |
注意1: COPY 指令的–from=0 参数,从前边的阶段中拷贝文件到当前阶段中,多个FROM语句时,0代表第一个阶段
注意2: scratch 是内置关键词,并不是一个真实存在的镜像。FROM scratch 会使用一个完全干净的文件系统,不包含任何文件(当然也可以替换为已存在的系统)
注意3: –from=0也可以替换为类似 –from=quay.io/coreos/etcd:v3.3.9 这种直接从hub镜像上的文件提取
0x04 特殊技巧
1 | 1 容器执行参数 |
1、容器执行参数
1 | # --net 设定网络模式 |
2、容器/镜像导入与导出
docker导入导出镜像可以使用docker save/load命令,导入导出容器可以使用docker export/import命令。具体区别如下:
作用 | 导入/导出对象 | 命令示例 | |
---|---|---|---|
docker save | 导出镜像(tar包) | 当目标为镜像时直接导出镜像; 当目标为容器时导出容器所使用的镜像 | docker save -o ‘压缩包名’.tar ‘镜像名’(‘容器名’) |
docker load | 导入镜像(tar包) | 导入镜像(不能指定镜像名称),覆盖已存在的同名镜像 | docker load -i ‘压缩包名’.tar |
docker export | 导出镜像(tar包) | 导出容器当前状态为镜像 | docker export -o ‘压缩包名’.tar ‘容器名’ |
docker import | 导入镜像(tar包) | 导入镜像(能指定镜像名称),夺取已存在的同名镜像名,原镜像只保留ID | docker import ‘压缩包名’.tar ‘新镜像名’ |
注意1: docker save保存的是镜像(image),docker export保存的是容器(container)
注意2: docker load用来载入镜像包,docker import用来载入容器包,但两者都会恢复为镜像
注意3: docker load不能对载入的镜像重命名,而docker import可以为镜像指定新名称
0x05 引用文献
[1]https://www.runoob.com/docker/docker-tutorial.html
[2]https://www.cnblogs.com/s-b-b/p/8533936.html
[3]https://blog.csdn.net/iov_aaron/article/details/97135158