跳到主要内容

Docker

使用 Docker,可以让应用的部署、测试和分发都变得前所未有的高效和轻松!

基础概念

镜像(Image)

Docker 镜像 是一个包含操作系统的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 不包含 任何动态数据,其内容在构建之后也不会被改变。比如:官方镜像 ubuntu:18.04 就包含了完整的一套 Ubuntu 18.04 最小系统的 root 文件系统。

镜像构建时,是分层构建和存储的。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。

容器(Container)

容器是镜像的实例化。镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

危险

容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。

按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者 绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。

仓库

存储镜像的仓库。类似 npm 仓库 之于 node 包。

一个 Docker Registry 中可以包含多个 仓库(Repository);每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像。

官方仓库: Docker Hub。还有其他公开的仓库,如 Red Hat 的 Quay.io;Google 的 Google Container Registry(Kubernetes 的镜像使用的就是这个服务);代码托管平台 GitHub 推出的 ghcr.io。

常用命令

获取镜像

docker pull 仓库名[:标签]

如:

docker pull ubuntu:18.04

运行

docker run -it --rm ubuntu:18.04 bash

说明:

  • -it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
  • --rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会删除,除非手动 docker rm
  • ubuntu:18.04:这是指用 ubuntu:18.04 镜像为基础来启动容器。
  • bash:放在镜像名后的是 命令,这里我们希望有个交互式 Shell,因此用的是 bash。

列出镜像

docker image ls

在 Docker 客户端可以看到更详细对信息。

构建镜像

docker build -t 镜像名称 Dockerfile所在文件夹的路径

定制镜像

用 Dockerfile 来定制镜像。 Dockerfile 里包含了一系列修改的指令。每个指令都会给改 image 增加一层。

常见

FROM 镜像名称: 标签

# 源数据
LABEL org.opencontainers.image.authors="Joel"
LABEL org.opencontainers.image.documentation="https://yeasy.gitbooks.io"

# 设置环境变量
ENV DEPLOY_ENV PRODUCTION

# 暴露端口的声明
EXPOSE 3000

WORKDIR /app/web

COPY package.json /app/web/package.json

RUN npm install --only=prod

# 将外面的文件拷贝到工作路径下去
COPY . /app/web/

RUN npm run build
提示

减少构建出的镜像体积小技巧

  1. 做一件事的多个 RUN 改成一个 RUN,用 & 来连接,以此来减少层数。
  2. 每个命令结束后,清除临时文件和缓存文件。

构建该镜像

cd Dockerfile所在文件夹
docker build . -t 构建出的镜像名称

docker 还支持对 GitHub 的 repo 或者压缩包来构建。

传构时传参,用 --build-arg key=value。如 docker build --build-arg SENTRY_DSN=abc --build-arg SENTRY_ORG=abc . -t xxx

ARG SENTRY_DSN # 获取到的参数
ENV NEXT_PUBLIC_SENTRY_DSN $SENTRY_DSN
RUN echo "NEXT_PUBLIC_SENTRY_DSN is: $NEXT_PUBLIC_SENTRY_DSN"

# ...
RUN NEXT_PUBLIC_SENTRY_DSN=$SENTRY_DSN \
NEXT_PUBLIC_SENTRY_ORG=$SENTRY_ORG \
NEXT_PUBLIC_SENTRY_PROJECT=$SENTRY_PROJECT \
npm run build

更多信息

信息

不推荐用 docker commit 来定制镜像。docker commit 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为 黑箱镜像,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体的操作。这种黑箱镜像的维护工作是非常痛苦的。

构建多种系统架构支持的 Docker 镜像

可以通过 manifest 来实现:详情

数据卷

数据卷 是一个可供一个或多个容器使用的特殊目录。

编排(Docker Compose)

启动一个项目时,如果需要多个容器,则需要编排。比如,后端一个容器,前端一个容器,数据库一个容器。

编排

docker-compose.yml 来编排。比如:

version: '3'
services:
web:
build: . # Dockerfile 所在文件夹。
ports:
- "5000:5000"

redis:
image: "redis:alpine"

db:
image: postgres:15-alpine
restart: always
environment:
POSTGRES_PASSWORD: xxx
POSTGRES_DB: xxx
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- ./volumes/db/data:/var/lib/postgresql/data
ports:
- "5432:5432"

image 会从本地镜像库寻找,如果没有则从 Docker Hub 下载。image 的名字可以是名称,或者是镜像 id 的一部分。

启动

docker-compose up -d

将 Docker 容器作为远程开发环境

无需本地安装开发工具,直接将 Docker 容器作为开发环境,具体参考:文档

资源