Docker教程


文档摘要

Docker 教程 目录: 镜像和容器的基本概念 安装 Docker 使用 Node.js 开发全栈 Web 应用 编写 Dockerfile 运行 Docker 镜像 推送至 Docker Hub 使用多阶段构建 Docker 基本概念 - 容器和镜像 详细的 Docker 概念和笔记请参阅此处 - Docker 概念 Docker 简介: Docker 是一个执行操作系统级虚拟化的计算机程序,也称为“容器化”。 容器的大小可以小到只有 50MB。 Docker 是一个帮助进行应用程序容器化的工具。

Docker 教程

目录:

  1. 镜像和容器的基本概念
  2. 安装 Docker
  3. 使用 Node.js 开发全栈 Web 应用
  4. 编写 Dockerfile
  5. 运行 Docker 镜像
  6. 推送至 Docker Hub
  7. 使用多阶段构建

1. Docker 基本概念 - 容器和镜像

  • 详细的 Docker 概念和笔记请参阅此处 - Docker 概念

  • Docker 简介:

    • Docker 是一个执行操作系统级虚拟化的计算机程序,也称为“容器化”。
    • 容器的大小可以小到只有 50MB。
    • Docker 是一个帮助进行应用程序容器化的工具。
  • 基本设计:

    硬件 --> 操作系统 --> 容器引擎 --> Bins/Libs --> 应用1
    --> Bins/Libs --> 应用2
    --> Bins/Libs --> 应用3

2. 安装 Docker

  • 在 Ubuntu 上安装:
sudo apt-get update sudo apt-get install docker.io
  • 另一种方法是安装官方 Docker 社区版(Community Edition),如下所示:
# Install Prerequisites sudo apt-get install ca-certificates curl gnupg lsb-release # Add dockers official gpg key sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # Setup repository echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # Install Docker Engine sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
  • 检查已安装版本

$ docker version

  • Docker 容器生命周期:
    • 过程:从 Docker Hub 拉取镜像到安装了 Docker 引擎的系统。
      从 Docker Hub 下载的内容是一个容器的镜像。
      运行镜像。(一旦运行镜像,它就变成了容器)
      可以运行、停止、删除容器

3. Node Web 应用

  • 让我们不要浪费宝贵的时间来构建 Node.js Web 应用,而是直接看看 Node 应用文件夹并在本地系统中运行它:

  • 我们将使用这个 Node.js + Express.js Web 应用来进行 Docker 容器化教程 ->> Node.js Web 应用

    cd node

    npm install

    node app.js

  • 访问 http://localhost:8080

4. 编写 Dockerfile

  • 您的 Dockerfile 指定在执行应用程序容器时包含的内容。 使用 Dockerfile 可以定义容器环境,并避免依赖项或运行时版本的不同。

  • 根据优化容器构建的指南,我们将通过减少镜像层数量并限制镜像的功能为单一目的来尽可能使我们的镜像高效——重新创建我们的应用程序文件和静态内容。

  • 在项目的根目录中创建 Dockerfile:

nano dockerfile

或者

touch dockerfile

  • Docker 镜像是通过一系列分层镜像构建而成的,这些镜像彼此叠加。 我们的第一个步骤将是添加构成应用程序基础的基镜像。

  • 让我们使用 node:10-alpine 镜像,因为此时这是推荐的 LTS 版本的 Node.js。 Alpine 镜像来自 Alpine Linux 项目,这有助于我们减小镜像大小。 有关 Alpine 镜像是否适合您的项目的更多信息,请参阅 Docker Hub Node 镜像页面下的 Image Variants 部分的完整讨论。

  • 添加以下 FROM 指令以设置应用程序的基础镜像:

FROM node:10-alpine

  • 此镜像包含 Node.js 和 npm。 每个 Dockerfile 必须以 FROM 指令开始。

  • 默认情况下,Docker Node 镜像包括一个非 root 用户 node,您可以使用它来避免以 root 身份运行应用程序容器。 不以 root 身份运行容器并仅在容器内限制所需的进程权限是一种推荐的安全实践。 因此,我们将使用 node 用户的主目录作为应用程序的工作目录,并在容器内将其设置为我们用户。 有关与 Docker Node 镜像一起工作的最佳实践的更多信息,请参阅此最佳实践指南。

  • 为了微调容器中应用程序代码的权限,让我们在 /home/node 中创建 node_modules 子目录以及 app 目录。 创建这些目录将确保它们具有我们希望的权限,这对于稍后在容器中使用 npm install 创建本地 node 模块非常重要。 除了创建这些目录外,我们还将所有权设置为我们的 node 用户:

RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app

  • 有关合并 RUN 指令的效用的更多信息,请参阅如何管理容器层的讨论。

  • 接下来,将应用程序的工作目录设置为 /home/node/app:

WORKDIR /home/node/app

  • 如果未设置 WORKDIR,则 Docker 将默认创建一个,因此显式设置它是明智的。

  • 接下来,复制 package.json 和 package-lock.json 文件(对于 npm 5+):

COPY package*.json ./

  • 添加此 COPY 指令在运行 npm install 或复制应用程序代码之前允许我们利用 Docker 的缓存机制。 在每次构建过程中,Docker 都会检查是否有该特定指令的缓存层。 如果我们更改了 package.json,这一层将被重建,但如果未更改,此指令将允许 Docker 使用现有图像层并跳过重新安装我们的 node 模块。

  • 为了确保所有应用程序文件(包括 node_modules 目录中的内容)都由非 root 用户 node 所有,在运行 npm install 之前切换到 node 用户:

USER node

  • 复制完项目依赖项并切换到我们的用户后,我们可以运行 npm install:

RUN npm install

  • 接下来,将应用程序代码及其适当的权限复制到容器中的应用程序目录:

COPY --chown=node:node . .

  • 这将确保应用程序文件由非 root 用户 node 所有。

  • 最后,公开容器上的端口 8080 并启动应用程序:

    EXPOSE 8080 CMD [ "node", "app.js" ]
  • EXPOSE 不发布端口,而是作为一种文档记录的方式,表明容器将在运行时发布的端口。 CMD 运行启动应用程序的命令——在这种情况下,node app.js。 请注意,每个 Dockerfile 中只应有一个 CMD 指令。 如果您包含多个指令,只有最后一个指令生效。

  • Dockerfile 可以做很多事情。 有关所有指令的完整列表,请参阅 Docker 的 Dockerfile 参考文档。

  • 完整的 Dockerfile 如下所示:

    FROM node:10-alpine RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app WORKDIR /home/node/app COPY package*.json ./ USER node RUN npm install COPY --chown=node:node . . EXPOSE 8080 CMD [ "node", "app.js" ]

5. 运行 Docker 镜像

  • 现在您可以使用 docker build 命令构建应用程序镜像。 使用 docker build 命令的 -t 标志将镜像标记为一个易于记忆的名称。 因为我们打算将镜像推送到 Docker Hub,所以让我们在标记中包含您的 Docker Hub 用户名。 我们将镜像标记为 nodejs-image-demo,但您可以自由替换为您自己的名称。 请记得将 your_dockerhub_username 替换为您的 Docker Hub 用户名:

    $ docker build -t your_dockerhub_username/nodejs-image-demo .

  • 点表示构建上下文是当前目录。

  • 构建镜像可能需要一两分钟。 一旦完成,检查您的镜像:

$ docker images

  • 现在可以使用 docker run 命令使用此镜像创建容器。 我们将在此命令中包含三个标志:

    -p:此选项将容器上的端口发布并映射到主机上的端口。 我们将使用主机上的端口 80,但如果您在该端口上有另一个进程正在运行,您可以根据需要修改此端口。 有关此操作方式的更多信息,请参阅 Docker 文档中关于端口绑定的讨论。
    -d:此选项将容器在后台运行。
    --name:此选项允许我们给容器一个易于记忆的名称。

  • 运行以下命令来构建容器:

    $ docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo

  • 一旦您的容器运行起来,您可以使用 docker ps 查看运行中的容器列表:

    $ docker ps

  • 当您的容器正在运行时,现在可以通过导航浏览器到 http://your_server_ip 来访问您的应用程序。 您将再次看到您的应用程序登录页面:

6 推送镜像到 Docker Hub

  • 通过将应用程序镜像推送到 Docker Hub 等注册表,您可以使其在构建和扩展容器时可用。 我们将通过将应用程序镜像推送到存储库并使用该镜像重新创建容器来演示其工作原理。

  • 推送镜像的第一步是登录到您在前提条件中创建的 Docker Hub 账户:

$ docker login -u your_dockerhub_username

  • 提示时,输入您的 Docker Hub 账户密码。 通过这种方式登录会在您的用户主目录中创建一个 ~/.docker/config.json 文件,其中包含您的 Docker Hub 凭据。

  • 现在可以使用之前创建的标签将应用程序镜像推送到 Docker Hub:your_dockerhub_username/nodejs-image-demo:

$ docker push your_dockerhub_username/nodejs-image-demo

  • 让我们通过销毁当前的应用程序容器和镜像并使用存储库中的镜像重新创建它们来测试镜像注册表的实用性。

  • 首先,列出您的运行中的容器:

    $ docker ps

  • 使用输出中列出的 CONTAINER ID 停止运行的应用程序容器。 请确保将下面突出显示的 ID 替换为您的 CONTAINER ID,例如:

$ docker stop e50ad27074a7

  • 使用 -a 标志列出您所有的镜像:

$ docker images -a

  • 您将看到以下输出,其中包括您的镜像名称 your_dockerhub_username/nodejs-image-demo 以及 node 镜像和其他构建镜像。

  • 使用以下命令删除已停止的容器以及所有镜像,包括未使用的或悬空的镜像:

$ docker system prune -a

  • 您现在已删除运行应用程序镜像的容器及其镜像本身。 有关删除 Docker 容器、镜像和卷的更多信息,请参阅《如何删除 Docker 镜像、容器和卷》。

  • 删除所有镜像和容器后,现在可以从 Docker Hub 拉取应用程序镜像:

$ docker pull your_dockerhub_username/nodejs-image-demo

  • 再次列出您的镜像:

$ docker images

  • 现在从您的 dockerhub 存储库运行拉取的镜像:

$ docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo

7 使用多阶段构建

  • 使用多阶段构建,您可以在 Dockerfile 中使用多个 FROM 指令。 每个 FROM 指令可以使用不同的基础,并且每个指令都开始一个新的构建阶段。 您可以选择性地将工件从一个阶段复制到另一个阶段,从而丢弃不需要保留在最终镜像中的所有内容。 您还可以通过在 FROM 指令中添加一个 AS <NAME> 来命名您的阶段。 为了展示其工作原理,让我们将 Dockerfile 改造为使用多阶段构建。

Dockerfile

### stage 1 (build) ### FROM golang:alpine3.15 as build # set working directory RUN mkdir -p /app WORKDIR /app # install app dependencies RUN go mod init github.com/Rosalita/GoViolin # add app COPY . /app # listener port at runtime EXPOSE 3000 # build RUN go build -o go # test HEALTHCHECK --interval=1m --timeout=20s --start-period=30s --retries=3 \ CMD go test || exit 1 ### stage 2 (run) ### FROM alpine as production WORKDIR /app COPY --from=build /app . # run ENTRYPOINT [ "./go" ]
  • 最终结果与以前一样,仍然是一个小巧的生产镜像,但复杂性显著降低。
  • 它是如何工作的? 第二个 FROM 指令以 alpine as production 镜像为基础开始一个新的构建阶段。 COPY --from=build /app . 行仅从上一个阶段复制构建工件到这个新阶段。 Go SDK 和任何中间工件都被丢弃,不会保存在最终镜像中。
  • 您可以从此链接 s403o/goapp 查看最终镜像,其最终大小为 50MB! :))))

声明:
本文件灏天文库团队进行了翻译。尽管我们力求准确,但请注意,翻译可能包含错误或不准确之处。原文档以其原始语言为准。我们不对因使用此翻译而产生的任何误解或误译负责。


作者与出处
原作者: Tikam02
来源:Tikam02
许可证:MIT
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: Tikam02 转发
评论区 (0)
U