Docker 基础入门

一、Docker 简介

Docker是用GO语言开发的应用容器引擎,基于容器化,沙箱机制的应用部署技术。可适用于自动化测试、打包,持续集成和发布应用程序等场景,包括阿里云,亚马逊在内的云计算服务商都采用了docker来打造serverless服务平台。它不仅仅可以部署项目,还可以用于数据库搭建,nginx服务搭建,nodejs、php等编程语言环境搭建。

PS: docker现已改名为moby

Docker中的三个重要概念

  • 镜像(image):分片的(只读)文件系统,由Dockerfile创建

    独立、易扩展、更效率

  • 容器(container):由Docker进程创建和管理的:文件系统 + 系统资源 + 网络配置 + 日志管理

    docker是docker镜像的运行环境,所以容器的概念就比较好理解了

  • 仓库(registry):用来远端存储docker镜像

    版本控制、变更管理、为持续集成与快速部署提供便利

二、Docker vs 虚拟机

Docker 基础入门_第1张图片

  1. 容器是应用层的抽象,它将代码和依赖关系打包在一起。 多个容器可以在同一台机器上运行,并与其他容器共享操作系统内核,每个容器在用户空间中作为独立进程运行。 容器占用的空间比VM少(容器映像的大小通常为几十MB),可以处理更多的应用程序,并且需要更少的VM和操作系统。
  2. 虚拟机(VM)是物理硬件的抽象,将一台服务器转变为多台服务器。 管理程序允许多台VM在单台机器上运行。 每个VM都包含操作系统的完整副本,应用程序,必要的二进制文件和库 - 占用数十GB。 虚拟机也可能很慢启动。

总结一下:

特性 容器 虚拟机
启动 秒级 分钟级
硬盘使用 一般为 MB 一般为 GB
性能 接近原生 弱于
系统支持量 单机支持上千个容器 一般几十个
开发/环境定制 方便(命令行、面向对象式) 进入虚拟机

相同点:

  1. 文件隔离/文件共享(沙箱)
  2. 资源隔离
  3. 网络隔离
  4. 支持多种宿主环境(扩展)
  5. 快照/镜像(版本控制/变更管理)

不同点:

  1. 不同的资源管理/依赖//释放(虚拟机占用更多的系统资源)
  2. 不同的应用运行环境
  3. Docker是写时复制
  4. 不同的日志方式(Docker收集日志,而虚拟机需要在虚拟系统里面看日志)
  5. 不同的交互方式(Docker偏shell,虚拟机偏GUI)

三、Docker的工作原理

Docker 基础入门_第2张图片
Docker是容器化部署技术,它主要作用在于通过运行容器来实现应用部署,而容器基于镜像运行。

简单地说,就是将你的项目和依赖包(基础镜像)打成一个带有启动指令的项目镜像,然后在服务器创建一个容器,让镜像在容器内运行,从而实现项目的部署。

服务器就是容器的宿主机,docker容器与宿主机之间是相互隔离的。

Docker:

使用基于java的tomcat镜像 -> docker run -> 指定端口/挂载webapp目录 -> 服务启动

  1. Docker会自己拉取镜像,若本地已经存在该镜像,则不用到网上去拉取

  2. 创建新的容器

  3. 分配文件系统并且挂着一个可读写的层,任何修改容器的操作都会被记录在这个读写层上,你可以保存这些修改成新的镜像,也可以选择不保存,那么下次运行改镜像的时候所有修改操作都会被消除

  4. 分配网络\桥接接口,创建一个允许容器与本地主机通信的网络接口

  5. 设置ip地址,从池中寻找一个可用的ip地址附加到容器上,换句话说,localhost并不能访问到容器

  6. 运行你指定的程序

  7. 捕获并且提供应用输出,包括输入、输出、报错信息

Docker的价值:

从应用架构角度:统一复杂的构建环境;

从应用部署角度:解决依赖不同、构建麻烦的问题,结合自动化工具(如jenkins)提高效率。

从集群管理角度:规范的服务调度服务发现负载均衡

四、使用Docker

4.1 安装

操作系统
Docker Desktop for Mac (macOS)
Docker Desktop for Windows (Microsoft Windows 10)

4.2 Docker国内加速

Docker镜像加速,主要是对docker pull拉取镜像操作进行网络加速优化:
需要注册阿里云的账号,登录容器Hub服务,在左侧的加速器帮助页面就会显示为你独立分配的加速地址。

Docker 基础入门_第3张图片
针对安装了Docker for Windows的用户,打开docker设置,Docker Engine 输入下面的配置,添加

"registry-mirrors": [
  "https://xxx.mirror.aliyuncs.com"
]

完整配置:

{
  "builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
  },
  "experimental": false,
  "features": {
    "buildkit": true
  },
  "registry-mirrors": [
    "https://xxx.mirror.aliyuncs.com"
  ]
}

五、使用 Docker 镜像

5.1 获取镜像

docker [image] pull NAME[:TAG]

NAME 是镜像仓库名称(用来区分镜像),TAG 是镜像的标签(往往用来表示版本信息)。如果不显式指定 TAG,则默认会选择 latest 标签

# 获取一个 Ubuntu 18.04 系统的基础镜像
docker pull ubuntu:18.04

在这里插入图片描述

注意:在不同的镜像仓库服务器的情况下,可能会出现镜像重名的情况。严格地讲,镜像的仓库名称中还应该添加仓库地址(注册服务器)作为前缀,只是默认使用的是官方 Docker Hub 服务,该前缀可以忽略

docker pull ubuntu:18.04 相当于 docker pull register.hub.docker.com/ubuntu:18.04

pull 子命令支持的选项主要包括:

选项 描述 示例
-a,–all-tags=true|false 是否获取仓库中的所有镜像,默认为否
–disable-content-trust 取消镜像的内容校验,默认为真 docker pull --disable-content-trust ubuntu

下载镜像到本地后,即可随时使用该镜像,例如利用该镜像创建一个容器,在其中运行 bash 应用,执行打印 “hello world” 命令:
在这里插入图片描述

5.2 查看镜像

5.2.1 使用 images 命令列出镜像

docker images or docker image ls
在这里插入图片描述
从列出信息中,可以看到几个字段信息:

  • REPOSITORY,来自于哪个仓库
  • TAG,镜像的标签信息
  • IMAGE ID,镜像 ID,如果两个镜像的 ID 相同,说明它们实际上指向了同一个镜像,只是具有不同的标签名称而已
  • CREATED,创建时间
  • SIZE,镜像大小

images 子命令支持的选项主要包括:

选项 描述 示例
-a,–all=true|false 列出所有(包括临时文件)镜像文件,默认为否
–digests=true|false 列出镜像的数字摘要值,默认为否
-f,–filter=[] 过滤列出的镜像
–no-trunc=true|false 对输出结果中太长的部分是否进行截断,默认为是
-q,–quiet=true|false 仅输出ID信息,默认为否 docker images -q

5.2.2 使用 tag 命令添加镜像标签

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

# 添加一个新的 myubuntu 镜像
docker tag ubuntu:18.04 myubuntu:18.04

在这里插入图片描述

myubuntu 跟 ubuntu 的镜像 ID 是完全一致的,实际上是指向了同一个镜像文件,只是别名不同而已。docker tag 命令添加的标签实际上起到了类似链接的作用

5.2.3 使用 inspect 命令查看详细信息

docker [image] inspect NAME[:TAG]

# 查看该镜像的详细信息,包括制作者、适应架构、各层的数字摘要等
docker inspect ubuntu:18.04

# 获取镜像的 Architecture 信息
docker inspect -f {{".Architecture"}} ubuntu:18.04
amd64

5.2.4 使用 history 命令查看镜像历史

docker history NAME[:TAG]

5.3 搜寻镜像

docker search [option] keyword

search 子命令支持的选项主要包括:

选项 描述 示例
-f,–filter filter 过滤输出内容
–format string 格式化输出内容
–limit int 限制输出结果个数,默认为 25 个
–no-trunc 不截断输出结果
# 搜索官方提供的带 nginx 关键字的镜像
docker search --filter=is-official=true nginx

# 搜索所有收藏数超过 4 的关键词包括 tensorflow 的镜像
docker search --filter=starts=4 tensorflow

5.4 删除和清理镜像

删除:docker rmi IMAGE or docker image rm IMAGE
清理:docker image prune

IMAGE 可以为标签或ID。当有该镜像创建的容器存在时,镜像文件默认是无法被删除的

rmi 子命令支持的选项主要包括:

选项 描述 示例
-f,-force 强制删除镜像,即使有容器依赖它
-no-prune 不要清理未带标签的父镜像

5.4.1 使用标签删除镜像

只删除某个标签的镜像

# 删除 myubuntu:18.04
docker rmi myubuntu:18.04

5.4.2 使用镜像ID删除镜像

镜像ID一样的都会被删除,比如利用某个镜像通过 docker tag 创建的镜像副本,它们的镜像ID是一样的

# 删除镜像ID是 5a214d77f5d7 的镜像
docker rmi 5a214d77f5d7

5.4.3 清理镜像

子命令支持的选项主要包括:

选项 描述 示例
-f,-force 强制删除镜像
-a,-all 删除所有无用镜像,不光是临时镜像
-filter filter 只清理给定过滤器的镜像
# 清理临时的遗留镜像文件层
docker image prune -f

5.5 创建镜像

创建镜像的方法主要有三种:基于已有镜像的容器创建、基于本地模板导入、基于 Dockerfile 创建。

5.5.1 基于已有镜像的容器创建

该方法主要是使用 docker [container] commit 命令。

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

子命令支持的选项主要包括:

选项 描述 示例
-c,–change=[] 提交的时候执行 Dockerfile 指令
-a,–author=“” 作者信息
-m,–message=“” 提交消息
-p,–pause=true 提交时暂停容器运行
# 启动容器,创建一个 test 文件,然后退出
docker run -it ubuntu:18.04 /bin/bash
root@f817585f00a5:/# touch test
root@f817585f00a5:/# exit
exit

记住容器ID为 f817585f00a5,此时该容器与原 ubuntu:18.04 镜像相比,已经发生改变,可以使用 docker [container] commit 命令来提交为一个新的镜像。提交时可以使用 ID 或名称来指定容器:

# 使用 commit 命令来提交一个新的镜像
docker commit -m "Added a new file" -a "Docker Newbee" f817585f00a5 test:0.1
sha256:9e62a170b9ef8ed0ddc1510a6ed0df7070a5e27069ff00cc76ad2282431a9bc8

# 查看本地镜像列表,会发现新创建的镜像已经存在
docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
test         0.1       9e62a170b9ef   2 minutes ago   63.1MB
myubuntu     18.04     5a214d77f5d7   14 months ago   63.1MB
ubuntu       18.04     5a214d77f5d7   14 months ago   63.1MB

5.5.2 基于本地模板导入

docker [image] import [OPTIONS] file|URL| - [REPOSITORY[:TAG]]

5.5.3 基于 Dockerfile 创建

最常见的方式。Dockerfile 是一个文本文件,利用给定的指令描述基于某个父镜像创建新镜像的过程。

一般,Dockerfile 共包括四部分:

  • 基础镜像信息
  • 维护者信息
  • 镜像操作指令
  • 容器启动时执行指令

1、一个简单的Koa应用:

const Koa = require('koa')
const app = new Koa()

// response
app.use(ctx => {
  ctx.body = 'Hello Koa!!'
})

app.listen(3000)

2、Dockerfile示例:

FROM node:10

LABEL [email protected]

# 创建 app 目录
WORKDIR /app

# 把 package.json,package-lock.json(npm@5+) 或 yarn.lock 复制到工作目录(相对路径)
COPY ["package.json","*.lock","./"]

# 打包 app 源码
# 特别注意:要指定工作目录中的文件名
COPY src ./src

# 使用.dockerignore文件,上面两个COPY合并成一个
# COPY . .

# 使用Yarn安装 app 依赖
# 如果你需要构建生产环境下的代码,请使用:
# --prod参数
RUN yarn --prod --registry=https://registry.npm.taobao.org

# 对外暴露端口 -p 4000:3000
EXPOSE 3000

CMD [ "node", "src/index.js" ]

3、使用docker build打包:

docker build -t ${your_name}/${image_name}:${tag} .

这里的your_name代表的是远程仓库中的用户名,或者仓库地址; image_name为镜像名称,tag是给镜像打的标签,用于版本控制。例如:

docker build -t lxc/koa:1.0 .

4、启动 run

# 把 3000 端口映射到 4000 上
docker run -d --name nodedemo -p 4000:3000 lxc/koa:1.0

使用docker ps来看运行状态
在这里插入图片描述

5.6 存出和载入镜像

5.6.1 存出镜像

docker save -o FILENAME IMAGE[:TAG]

子命令支持的选项主要包括:

选项 描述 示例
-o,-output 导出镜像到指定参数中
# 导出本地的 ubuntu:18.04 镜像为文件 ubuntu_18.04.tar
docker save -o ubuntu_18.04.tar ubuntu:18.04

之后就可以通过复制 ubuntu_18.04.tar 文件将该镜像分享给他人

5.6.2 载入镜像

docker load -i IMAGE[:TAG]

子命令支持的选项主要包括:

选项 描述 示例
-i,-input 从指定文件中读取镜像内容
# 导出本地的 ubuntu:18.04 镜像为文件 ubuntu_18.04.tar
docker load -i ubuntu_18.04.tar

导入成功后,可以使用 docker images 命令进行查看,与原镜像一致

5.7 上传镜像

docker push IMAGE[:TAG] or docker push [REGISTRY_HOST[:REGISTRY_PORT]/]IMAGE[:TAG]

默认上传到 Docker Hub 官方仓库(需要登录)。

如:用户 user 上传本地的 test:latest 镜像

# 先添加新的标签 user/test:latest
docker tag test:latest user/test:latest

# 上传到远程
docker push user/test:latest

第一次上传时,会提示输入登录信息进行注册,之后登录信息会记录到本地 ~/.docker 目录下

六、操作 Docker 容器

6.1 创建容器

6.1.1 新建容器

docker create CONTAINER[:TAG]

# 新建容器
docker create -it ubuntu:latest

Docker 基础入门_第4张图片
使用 docker create 命令新建的容器处于停止状态,可以使用 docker start 命令来启动它

6.1.2 启动容器

docker start CONTAINER ID or docker start NAMES

# 启动新建的容器
docker start 97d41053c282
97d41053c282

docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
97d41053c282   ubuntu    "bash"    4 minutes ago   Up 8 seconds             tender_bohr

6.1.3 新建并启动容器

docker run IMAGE[:TAG]

6.1.4 查看启动中的容器

docker ps or docker container ls

子命令支持的选项主要包括:

选项 描述 示例
-a 查看所有容器

6.1.45 查看容器

docker logs CONTAINER ID

子命令支持的选项主要包括:

选项 描述 示例
-details 打印详尽信息
-f,-follow 持续保持输出
-since string 输出从某个时间开始的日志
-tail string 输出最近的若干日志
-t 显示时间戳信息
-until string 输出从某个时间之前的日志

6.2 停止容器

6.2.1 暂停容器

暂停:docker pause CONTAINER ID or docker pause NAMES
恢复运行:docker unpause CONTAINER ID or docker unpause NAMES

6.2.2 终止容器

docker stop CONTAINER ID or docker stop NAMES

该命令会首先向容器发送 SIGTERM 信号,等待一段时间后(默认 10s),再发送 SIGKILL 信号来终止容器

自动清除所有处于停止状态的容器:docker container prune
直接发送 SIGKILL 信号来终止容器:docker kill CONTAINER ID
将运行中的容器先终止,然后再启动:docker restart CONTAINER ID

6.3 进入容器

docker exec CONTAINER ID

子命令支持的选项主要包括:

选项 描述 示例
-d,–detach 在容器中后台执行命令
–detach-keys=“” 指定将容器切回后台的按键
–e,–env=[] 指定环境变量列表
-i,–interactive=true|false 打开标准输入接受用户输入命令,默认值为 false
–privileged=true|false 是否给执行命令以高权限,默认值为 false
-t,–tty=true|false 分配伪终端,默认值为 false
-u,–user=“” 执行命令的用户名或ID
# 进入刚创建的容器中,并启动一个 bash
docker exec -it 97d41053c282 /bin/bash
root@97d41053c282:/#

6.4 删除容器

docker rm CONTAINER ID

默认情况下,docker rm 命令只能删除已经处于终止或退出状态的容器

子命令支持的选项主要包括:

选项 描述 示例
-f,–force=false 是否强制终止并删除一个运行中的容器
-l,–link=false 删除容器的连接,但保留容器
-v,–volumes=false 删除容器挂载的数据卷

6.5 导入和导出容器

# 导出容器 97d41053c282 到文件 test_for_run.tar 文件
docker export -o test_for_run.tar 97d41053c282

# 导入 test_for_run.tar 文件到系统中
docker import test_for_run.tar - test/ubuntu:v1.0

6.6 查看容器

6.6.1 查看容器详情

docker container inspect CONTAINER ID or docker container inspect NAMES

6.6.2 查看容器内进程

docker top CONTAINER ID or docker top NAMES

6.6.3 查看统计信息

docker stats CONTAINER ID or docker stats NAMES

七、Docker 数据管理

容器中管理数据主要有两种方式:

  1. 数据卷:容器内数据直接映射到本地主机环境
  2. 数据卷容器:使用特定容器维护数据卷

7.1 数据卷

一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器

7.1.1 创建数据卷

# 在本地创建一个数据卷
docker volume create -d local test
test

除了 create 子命令外。docker volume 还支持

  • inspect:查看详细信息
  • ls:列出已有数据卷
  • prune:清理无用数据卷
  • rm:删除数据卷

7.1.2 绑定数据卷

在用 docker run 命令的时候,可以使用 -mount 选项来使用数据卷

# 使用 training/webapp 镜像创建一个 Web 容器,并创建一个数据卷挂载到容器的 /opt/webapp 目录
docker run -d -P --name web --mount type=bind,source=/webapp,destination=/opt/webapp training/webapp python app.py

7.2 数据卷容器

目的是提供数据卷给其他容器挂载

# 创建一个数据卷容器 dbdata,并在其中创建一个数据卷挂载到 /dbdata
docker run -it -v /dbdata --name dbdata ubuntu

在其他容器中使用 --volumes-from 来挂载 dbdata 容器中的数据卷,例如创建 db1 和 db2 两个容器,并从dbdata 容器挂载数据卷

docker run -it --volumes-from dbdata --name db1 ubuntu
docker run -it --volumes-from dbdata --name db2 ubuntu

此时,容器 db1 和 db2 都挂载同一个数据卷到相同的 /dbdata 目录,三个容器任何一方在该目录下的写入,其他容器都可以看到

八、端口映射与容器互联

有时候,需要多个容器之间能够互相访问到对方的服务。Docker 除了通过网络访问外,还提供了两个很方便的功能来满足服务访问的基本需求:一个是允许映射容器内应用的服务端口到本地宿主主机;另一个是互联机制实现多个容器间通过容器名来快速访问

8.1 端口映射实现容器访问

通过 -p 或 -P 参数来指定端口映射。当使用 -P(大写)标记时,Docker 会随机映射一个 49000 ~ 49900 的端口到内部容器开放的网络端口

# 随机分配端口
docker run -d -P training/webapp python app.py

# 查看
docker ps -l

# 映射到指定地址的指定端口,比如 localhost 地址 127.0.0.1
docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py

8.2 互联机制实现便捷互访

容器的互联是一种让多个容器中的应用进行快速交互的方式。它会在源和接收容器之间创建连接关系,接收容器可以通过容器名快速访问到源容器,而不用制定具体的IP地址。

8.2.1 自定义容器命名

连接系统依据容器的名称来执行。因此,首先需要自定义一个好记的容器命名。虽然当创建容器的时候,系统会默认会分配一个名字,但自定义命名有两个好处:

  • 比较好记
  • 当要连接其他容器时候(即便重启),也可以使用容器名而不用改变
# 使用 --name 标记可以为容器自定义命名
docker run -d -P --name web training/webapp python app.py

# 查看容器名
docker inspect -f {{".Name"}} 97d41053c282

8.2.2 容器互联

# 创建一个新的数据库容器
docker run -d --name db training/postgres

# 然后创建一个新的 web 容器,并将它连接到 db 容器
docker run -d -P --name web --link db:db training/webapp python app.py

–link 参数的格式为 --link name:alias,其中 name 是要链接的容器的名称,alias 是别名

九、Dockerfile

配置文件,用来快速创建自定义的镜像

9.1 配置指令

9.1.1 ARG

定义创建镜像过程中使用的变量
格式为: ARG [=<\default value>]
当镜像编译成功后,ARG 指定的变量将不再存在(ENV 指定的变量将在镜像中保留)

9.1.2 FROM

指定所创建镜像的基础镜像
格式为:FROM [:tag]

任何 Dockerfile 中第一条指令必须为 FROM 指令。并且,如果在同一个 Dockerfile 中创建多个镜像时,可以使用多个 FROM 指令(每个镜像一次)

ARG VERSION=9.3
FROM debian:${VERSION}

9.1.3 LABEL

为生成的镜像添加元数据标签信息
格式为:LABEL = =
LABEL version="1.0.0" date="2020-01-01"

9.1.4 EXPOSE

声明镜像内服务监听的端口
格式为:EXPOSE = =
EXPOSE 22 80 8443

9.1.5 ENV

指定环境变量
格式为:ENV = =ENV
ENV key1=value1 key2=value2

9.1.6 ENTRYPOINT

指定镜像的默认入口命令
支持两种格式:

  • ENTRYPOINT [“executable”, “param1”, “param2”]: exec 调用执行
  • ENTRYPOINT command param1 param2

此时,CMD 指令指定值将作为根命令的参数

每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效

9.1.7 VOLUME

创建一个数据卷挂载点
格式为:VOLUME [“/data”]

9.1.8 USER

指定运行容器时的用户名或UID
格式为:USER daemon

9.1.9 WORKDIR

为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录
格式为:WORKDIR /path/to/workdir
可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如:

WORKDIR /a
WORKDIR b
WORKDIR c

则最终路径为 /a/b/c
因此,为了避免出错,推荐 WORKDIR 指令中只使用绝对路径

9.1.10 ONBUILD

指定当基于所生成镜像创建子镜像时,自动执行的操作指令
格式为:ONBUILD [INSTRUCTION]

9.1.11 STOPSIGNAL

指定所创建镜像启动的容器接受退出的信号值
STOPSIGNAL signal

9.1.12 HEALTHCHECK

配置所启动容器如何进行健康检查
格式有两种:

  • HEALTHCHECK [OPATIONS] CMD command: 根据所执行命令返回值是否为 0 来判断
  • HEALTHCHECK NONE: 禁止基础镜像中的健康检查

9.1.13 SHELL

指定其他命令使用 shell 时的默认 shell 类型
默认值为 [“/bin/sh”, “-c”]

9.2 操作指令

9.2.1 RUN

运行指定命令
格式为:RUN RUN [“executable”, “param1”, “param2”]

注意:后者指令会被解析为 JSON 数组,必须使用双引号。前者默认将在 shell 终端中运行命令,即 /bin/sh -c;后者使用 exec 执行,不会启动 shell 环境

当命令较长时可以使用\来换行。例如:

RUN apt-get update \
    && ...

9.2.2 CMD

指定启动容器时默认执行的命令
支持三种格式:

  • CMD [“executable”, “param1”, “param2”]: 相当于执行 executable param1 param2,推荐方式
  • CMD command param1 param2: 在默认的 Shell 中执行,提供给需要交互的应用
  • CMD [“param1”, “param2”]: 提供给 ENTRYPOINT 的默认参数

每个 Dockerfile 只能有一条 CMD 命令。如果有多条命令,只有最后一条会被执行

9.2.3 ADD

添加内容到镜像
格式为:ADD
该命令将复制指定的 路径下的内容到容器中的 路径下

其中 可以是 Dockerfile 所在目录的一个相对路径(文件或目录);也可以是一个 URL; 可以是镜像内绝对路径,或者相对于工作目录(WORKDIR)的相对路径

9.2.4 COPY

复制内容到镜像
格式为:COPY
COPY 与 ADD 指令功能类似,当使用本地目录为源目录时,推荐使用 COPY

9.3 创建镜像

编写完 Dockerfile 之后,可以通过 docker [image] build 命令来创建镜像
格式为:docker build [OPTIONS] PATH | URL | -
该命令将读取指定路径下(包括子目录)的 Dockerfile,并将该路径下所有数据作为上下文发送给 Docker 服务端。碰到 ADD、COPY、RUN 指令会生成一层新的镜像。如果创建成功,会返回最终镜像的 ID

# 上下文路径为 /tmp/docker_builder/, 生成镜像标签为 builder/first_image:1.0.0
docker build -t builder/first_image:1.0.0 /tmp/docker_builder/

9.3.1 父镜像

大部分情况,生成新的镜像都需要通过 FROM 指令来指定父镜像。父镜像是生成镜像的基础,会直接影响到所生成镜像的大小和功能。

两种镜像选择作为父镜像:

  1. 基础镜像
    不存在 FROM 指令,或者基于 scratch 镜像(FROM scratch),这意味着其在整个镜像树中处于根的位置
  2. 普通镜像
    由第三方创建,基于基础镜像

定义一个简单的基础镜像,将用户提前编译好的二进制可执行文件 binary 复制到镜像中,运行容器时执行 binary 命令:

FROM scratch
ADD binary /
CDM ["/binary"]

9.4 docker-compose

通过 Docker-Compose 用户可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建

Compose 中有两个重要的概念:

  • 服务 (service) :一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
  • 项目 (project) :由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。

Docker Desktop 自带 docker-compose

例子

# 创建一个 test-mysql 容器
version: '3'
services:
  mysql:
    image: mysql
    container_name: test-mysql
    ports:
    - "8000:3306"
    environment:
    - MYSQL_ROOT_PASSWORD=123456

在此文件的当前目录下,使用docker-compose up -d来执行(默认执行 docker-compose.yml)
指定执行: docker-compose -f xxx.yml up -d

两个复杂的应用:

# restart: always 作用:当服务器(docker-image)重启之后,这个容器就会自动启动
version: '3.1'
services:
  mongo:
    image: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: 123456

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: 123456

你可能感兴趣的:(前端工程化,docker,学习,服务器)