You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

357 lines
20 KiB
Markdown

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Docker镜像学习
> [官网文档](https://docs.docker.com/engine/reference/commandline/build/) [BuildFile]()
## 镜像构建流程
![构建镜像](assets/images/DockerBuild.png)
## 构建镜像的三种方法
+ 基于现有容器,使用 `docker commit` 命令构建
```shell
# 1 创建容器,执行相关操作,之后退出
docker run -it ubuntu:18.04 /bin/bash
docker exec -it xxxxxxxx
# 2 基于该容器使用构建新的镜像
docker commit -m "new_image" -a "cnLinuxer" b66 myubuntu:v1
参数解释:
-m选项指定了新镜像的提交信息
-a标注作者信息
b66是容器ID
myubuntu:v1是指定的新镜像名称。
# 3 使用新镜像
docker images
docker run -it ubuntu:18.04 /bin/bash
```
+ 基于本地模板,使用 `docker import` 导入
```shell
# 1 将现有容器,导出为模板文件
docker export b66 > /root/myubuntu.tar
# 2 模板文件导入为镜像
docker import /root/myubuntu.tar ruyu/ubuntu:18.04
# 3 使用新镜像
docker images
docker run xxxx
```
+ 基于Dockerfile文件使用 `docker build` 构建
```tex
# 1 编写Dockerfile文件
文件内容示例
#指定父镜像
FROM centos:7.5.1804
#指定维护者信息
MAINTAINER mynginx
#将本地nginx软件包上传至容器/usr/local/下
ADD nginx-1.11.1.tar.gz /usr/local
#yum安装依赖软件
RUN yum -y install vim wget gcc gcc-c++ make openssl-devel pcre-devel
#进入nginx工作目录
WORKDIR /usr/local/nginx-1.11.1/
#编译并安装nginx服务
RUN ./configure --prefix=/usr/local/nginx && make && make install
#关闭nginx后台运行
RUN echo "daemon off;" >> /usr/local/nginx/conf/nginx.conf
#添加nginx的环境变量
ENV PATH /usr/local/nginx/sbin:$PATH
#将容器的80端口映射出来
EXPOSE 80
#执行nginx命令启动nginx
CMD ["nginx"]
# 2 docker build 构建镜像
docker build -f Dockerfile -t mynginx:v1 .
```
## 构建过程(docker build -f Dockerfile -t name .)
> docker是c/s架构c为docker clis为驻守服务进程。
> docker build 构建镜像时cli只负责把命令和相文件传递给服务进程服务程序接收命令和文件、创建构建上下文、执行构建并产出镜像。
![build](assets/images/build2.png)
## docker build 命令
```shell
# docker build 详解
# 语法
docker build [OPTIONS] PATH|URL|本地文本文件
# 参数可以是三种资源:Git存储库、tar压缩包和文本文件
git库示
示例docker build https://github.com/docker/rootfs.git#container:docker
Build Syntax Suffix Commit Used Build Context Used
myrepo.git refs/heads/master /
myrepo.git#mytag refs/tags/mytag /
myrepo.git#mybranch refs/heads/mybranch /
myrepo.git#pull/42/head refs/pull/42/head /
myrepo.git#:myfolder refs/heads/master /myfolder
myrepo.git#master:myfolder refs/heads/master /myfolder
myrepo.git#mytag:myfolder refs/tags/mytag /myfolder
myrepo.git#mybranch:myfolder refs/heads/mybranch /myfolder
tar包
示例docker build http://server/context.tar.gz
文件文件:
Powershell示例Get-Content Dockerfile | docker build -
```
Options
| 名称与速记 | 默认 | 描述 |
| ------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--add-host` | | 添加自定义主机到 IP 的映射 hostip |
| `--build-arg` | | 设置构建时变量 |
| `--cache-from` | | 要考虑用作缓存源的图像 |
| `--cgroup-parent` | | 容器的可选父 cgroup |
| `--compress` | | 使用 gzip 压缩构建上下文 |
| `--cpu-period` | | 限制 CPU CFS完全公平的调度程序期限 |
| `--cpu-quota` | | 限制 CPU CFS完全公平的调度程序配额 |
| `--cpu-shares`,`-c` | | CPU 份额(相对权重) |
| `--cpuset-cpus` | | 允许执行的 CPU 0-3 01 |
| `--cpuset-mems` | | 允许执行的 MEM 0-3 01 |
| `--disable-content-trust` | `true` | 跳过镜像验证 |
| `--file`,`-f` | | Dockerfile 的名称(默认值为"PATH/Dockerfile" |
| `--force-rm` | | **始终删除中间容器** |
| `--iidfile` | | 将映像 ID 写入文件 |
| `--isolation` | | 容器隔离技术 |
| `--label` | | 设置图像的元数据 |
| `--memory`,`-m` | | 内存限制 |
| `--memory-swap` | | 交换限制等于内存加交换:"-1",用于启用无限制交换 |
| `--network` | | [**原料检修 1.25+**](https://docs.docker.com/engine/api/v1.25/) 在构建期间设置 RUN 指令的网络模式 |
| `--no-cache` | | 构建映像时不要使用缓存 |
| `--output`,`-o` | | [**1.40+ 原料药**](https://docs.docker.com/engine/api/v1.40/) 输出目标(格式:类型=本地dest=路径) |
| `--platform` | | [**产品信息 1.38+**](https://docs.docker.com/engine/api/v1.38/) 如果服务器支持多平台,则设置平台 |
| `--progress` | `auto` | 设置进度输出类型自动、普通、tty。使用普通版显示容器输出 |
| `--pull` | | 始终尝试拉取较新版本的映像 |
| `--quiet`,`-q` | | 成功时禁止显示生成输出并打印图像 ID |
| `--rm` | `true` | **成功生成后删除中间容器** |
| `--secret` | | [**原料检修 1.39+**](https://docs.docker.com/engine/api/v1.39/) 要向构建版本公开的秘密文件(仅当启用 BuildKit 时id=mysecretsrc=/local/secret |
| `--security-opt` | | 安全选项 |
| `--shm-size` | | /dev/shm 的大小 |
| `--squash` | | [**实验性(守护进程)**](https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file)[**原料检修 1.25+**](https://docs.docker.com/engine/api/v1.25/) 将新构建的图层压缩为单个新图层 |
| `--ssh` | | [**原料检修 1.39+**](https://docs.docker.com/engine/api/v1.39/) 要向构建版本公开的 SSH 代理套接字或密钥(仅当启用了 BuildKit 时格式default\|<id>[=<socket>\|<key>[<key>]] |
| `--stream` | | 流附加到服务器以协商生成上下文 |
| `--tag`,`-t` | | 名称和标签(可选)采用"名称:标签"格式 |
| `--target` | | 设置要生成的目标生成阶段。 |
| `--ulimit` | | 乌利米特选项 |
> **特别注意**:
>
> 不要将 根目录 用作生成上下文的 因为这会导致生成将硬盘驱动器的全部内容传输到 Docker 守护程序。
>
> 推荐作法在空目录中放Dockerfile文件把需要的文件全部复制到Dockerfile目录或子目录中。
## 构建环境
1. Dockerfile中所用的所有文件一定要和Dockerfile文件在同一级父目录下可以为Dockerfile父目录的子目录
2. Dockerfile中相对路径默认都是Dockerfile所在的目录
3. 因Docker构建的分层构建联合挂载的特性Dockerfile中,每一条指令被视为一层,尽量一行写多个指令(&&连接 \用来分行)。
4. 约定:指令大写,内容小写
```shell
# 构建流程
# docke build . 默认构建
# 输出,#行为手动添加的说明
# 加载 Dockerfile 文件
=> [internal] load build definition from Dockerfile 0.0s
# 把 dockerfile 文件传输到Docker守护进程服务大小为 149B
=> => transferring dockerfile: 149B 0.0s
# 加载.dockerignore(Dockerfile目录下不上传文件配置文件) 文件
=> [internal] load .dockerignore 0.0s
# 传输构建上下文会传Docfile目录及子目录中除.dockerignore配置外的所有文件及文件夹
=> => transferring context: 2B 0.0s
# 从基础镜像加载元数据
=> [internal] load metadata for docker.io/library/centos:latest 3.0s
# 加载构建上下文
=> [internal] load build context 0.0s
# 传输构建上下文
=> => transferring context: 125B 0.0s
# 构建第一阶段:下载与验证基础镜像
=> [1/2] FROM docker.io/library/centos@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177 10.8s
=> => resolve docker.io/library/centos@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177 0.0s
=> => sha256:a1d0c75327776413fa0db9ed3adcdbadedc95a662eb1d360dad82bb913f8a1d1 83.52MB / 83.52MB 7.0s
=> => sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177 762B / 762B 0.0s
=> => sha256:a1801b843b1bfaf77c501e7a6d3f709401a1e0c83863037fa3aab063a7fdb9dc 529B / 529B 0.0s
=> => sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6 2.14kB / 2.14kB 0.0s
=> => extracting sha256:a1d0c75327776413fa0db9ed3adcdbadedc95a662eb1d360dad82bb913f8a1d1
# 构建第二阶段
# 执行命令
=> [2/2] ADD ./project/ /usr/local/app/ 3.6s
# 导出镜像
=> exporting to image 0.3s
# 导出镜像层
=> => exporting layers 0.0s
# 写入镜像文件
=> => writing image sha256:9f21ab65d16f8a8599aec0ba0c1b31b806ae675be2701a6d671ec42887ab5e56
0.0s
# 给镜像打标签
=> => naming to docker.io/library/mycentos:study1 0.0s
```
## Dockerfile文件
> Dockerfile是用来定制镜像的文本文件内容为构Docker建镜像的一条条指令由Docker build 命令使用构建Docker镜像。
## 文件组成(注释与指令)
> \# 开头的为注释行
>
> INSTRUCTION arguments
>
> 通常包含4部分
>
> 基础镜像信息、维护者信息、 镜像操作指令和容器启动时执行指令新版“维护者信息”放在LABLE中指定
>
> 执行按照Dockerfile指令顺序从上到下依次执行。
```dockerfile
# 这是一个示例Dockerfile文件
FROM busybox
MAINTAINER username <demo@163.com>
ENV file=app
ADD ./project/ /usr/local/$file/
```
## 指令
> 指令,不区分大小写,但按惯例指令名一律大写,指令内容小写
+ FROM
> FROM 指令必须是非注释的第一个指令(新版AGU指令可值于前面) 可以使用 “ AS 别名” 提供别名,在路另外使用( --from=别名)。
>
> 指定了基础镜像,后面的所有指令都是运行在该基础镜像环境上的。
>
> 如果不以任何镜像为基础那么写法为FROM scratch
```dockerfile
#语法格式
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest摘要即md5值>
# 特殊例子
#不以任何镜像为基础(内置空白镜像)
FROM scratch
# busybox是一个软件工具箱镜像集成了linux中几百个常用的linux命令以及工具。
# 大小只有1.2M,适合用来测试
FROM busybox
# .net core sdk
FROM mcr.microsoft.com/dotnet/sdk:2.1 AS build
```
+ RUN
> RUN指令在**docker build** 时运行,用于执行命令并创建新的镜像层,通常用于安装软件包。
>
> 可以在Docker build输出中看到执行详情
```shell
# run 有两种方式
1. RUN <command>
解释shell形式该命令在 shell 中运行。默认情况下:
Linux上为 /bin/sh -c : -c 参数:把后面的命令(字符串)当成一个整体来执行
Windows为 cmd /S /C : /C即 /Close 命令运行之后关闭窗口(/K 命令运行之后保持窗口不关闭)
/S
2. RUN ["executable", "param1", "param2"]
exec形式可以避免 shell 字符串冗余,以及使用不包含指定 shell 可执行文件的基本映像的命令。
要使用除"/bin/sh"以外的其他 shell请使用传入所需 shell 的exec形式
# 该指令将在当前镜像之上的新层中执行任何命令并提交结果。生成的已提交映像将用于下一步中。
```
```shell
# 示例
FROM busybox
WORKDIR /app
RUN /bin/sh -c 'echo 我是shell方式执行后写入的内容 > demo.txt'
RUN ["/bin/sh", "-c", "echo exec方式执行后写入的内容 > demo2.txt"]
# 说明因为RUN指令是在docker build时执行的所以docker run后终端上是没有回显的用输入文件的方式验证是否执行成功了。
# docker build --rm -f Dockerfile.Run -t study:buildrun1 .
# docker run --rm -it --name runstudy1 study:buildrun1
# pwd 查看当前目录
# ls 命令查看是否有demo.txt demo2.txt文件
# cat demo.txt 查看内容
```
+ CMD
> CMD命令设置容器启动后默认执行的命令及其参数但CMD设置的命令能够被docker run命令后面的命令行参数替换。
```shell
# cmd 三种方式
CMD ["executable","param1","param2"] (执行形式,这是首选形式)
CMD ["param1","param2"]作为ENTRYPOINT 的默认参数)
CMD command param1 param2 (外壳形式)
```
+ LABLE
> 标签:将元数据添加到镜像,键值对的形式。值包含空格时,使用双引号;包含特殊字符时,使用转义符 `\` 这在K8S筛选、管理镜像时很有用。
```textile
LABEL <key>=<value> <key>=<value> <key>=<value>
或者
LABLE <key>=<value>
LABLE <key>=<value>
```
> 一个镜像中可以有多个标签。可以在一行上指定多个标签,这在 Docker 1.10 之前,将减少最终映像的大小,但之后不需要如此。仍然可以选择在一条指令中以下列两种方式之一指定多个标签:
```dockerfile
LABEL multi.label1="value1" multi.label2="value2" other="value3"
```
```dockerfile
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
```
> 镜像会继承基本图像或父镜像中的标称如果标签已存在但具有不同的值则最近应用的值将覆盖之前设置的任何值。类似CSS
> 使用如下命令查看镜像的标签。
>
> ```
> docker image inspect --format='' imageName
> -- format 遵循Go模板语法使用需要学习例如
> docker image inspect --format="{{.ContainerConfig.Labels}}" centos
> ```