跳转至

二、基于 Dockerfile 构建并运行镜像

本文是《Docker必知必会系列》第二篇,原文发布于个人博客:悟尘记

上一篇:Docker必知必会系列(一):Docker 基础入门及架构介绍

构建并运行镜像

要构建一个容器,需要做很多的工作,设置很多的配置,如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么经常被提及的无法重复、镜像构建透明性、体积等问题就都会解决。 这个脚本就是 Dockerfile。

准备 Dockerfile 文件

下载示例项目,请在终端中运行以下命令:

curl -LO https://github.com/dockersamples/node-bulletin-board/archive/master.zip
unzip master.zip
cd node-bulletin-board-master/bulletin-board-app

node-bulletin-board项目是一个简单的公告板应用程序,使用 Node.js 编写。在此示例中,假设您编写了此应用程序,现在正尝试对其进行容器化。

Dockerfile 描述如何为容器组装专用文件系统,并且还可以包含一些元数据,这些元数据描述了如何基于该镜像运行容器。公告板应用程序 Dockerfile 内容如下:

# Use the official image as a parent image.
FROM node:current-slim

# Set the working directory.
WORKDIR /usr/src/app

# Copy the file from your host to your current location.
COPY package.json .

# Run the command inside your image filesystem.
RUN npm install

# Inform Docker that the container is listening on the specified port at runtime.
EXPOSE 8080

# Run the specified command within the container.
CMD [ "npm", "start" ]

# Copy the rest of your app's source code from your host to your image filesystem.
COPY . .

编写 Dockerfile 是容器化应用程序的第一步,这些 Dockerfile 命令是构建镜像的步骤。 这个步骤如下:

  • 使用 FORM 指定基于已经存在的 node:current-slim 基础镜像构建。这是一个由 nodejs 官方构建的镜像。
  • 使用 WORKDIR 指定所有后续操作均从镜像文件系统中的 /usr/src/app 目录中执行(而不是主机的文件系统中)。
  • 将文件 package.json 从主机复制到镜像中的当前位置(.)(复制到 `/usr/src/app/package.json
  • 在镜像文件系统中运行命令 npm install(读取 package.json 以确定并安装应用程序依赖)
  • 将应用的其余源代码从主机复制到镜像文件系统。

这些步骤与在主机上设置和安装应用程序所采取的步骤几乎相同。但是,将它们保存为 Dockerfile 可以使您在可移植的隔离 Docker 镜像中执行相同的操作。

上面的步骤构建了我们镜像的文件系统,但是 Dockerfile 中还有其他几行。

  • CMD 指令在镜像中指定一些元数据,该元数据描述了如何基于该镜像运行容器。在本示例中该图像的容器化过程是 npm start

  • EXPOSE 8080 通知 Docker 该容器在运行时监听 8080 端口。

上面是组织一个简单的 Dockerfile 的方法。始终以 FROM 命令开头,然后按照步骤构建您的私有文件系统,并以任何元数据规范作为结束。 Dockerfile 指令比上面看到的要多。有关完整列表,请参阅 Dockerfile 参考

构建并测试镜像

现在您已经有了一些源代码和一个 Dockerfile,现在该构建您的第一个镜像,并确保从其启动的容器能够按预期工作。让我们构建您的公告板图像:

docker build --tag bulletinboard:1.0 .

您将看到 Docker 逐步完成 Dockerfile 中的每条指令,并逐步构建镜像:

Sending build context to Docker daemon  45.57kB
Step 1/7 : FROM node:current-slim
current-slim: Pulling from library/node
48839397421a: Pull complete
cbb6511d79bf: Pull complete
04ec6202052a: Pull complete
29c5eab4674c: Pull complete
8df5bb5f8d2e: Pull complete
Digest: sha256:c92fad90875a6ce7251c72701f9c88e1e3f3efc2eb1d7d1ffb2184204e4f7d98
Status: Downloaded newer image for node:current-slim
 ---> 6d9a17519d40
Step 2/7 : WORKDIR /usr/src/app
 ---> Running in 9dfd5c099558
Removing intermediate container 9dfd5c099558
 ---> 6062c6d2e488
Step 3/7 : COPY package.json .
 ---> 2ddc37525da9
Step 4/7 : RUN npm install
 ---> Running in 6ce3fed8ecd7

> ejs@2.7.4 postinstall /usr/src/app/node_modules/ejs
> node ./postinstall.js

Thank you for installing EJS: built with the Jake JavaScript build tool (https://jakejs.com/)

npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN vue-event-bulletin@1.0.0 No repository field.
npm WARN The package morgan is included as both a dev and production dependency.

added 91 packages from 168 contributors and audited 221 packages in 16.854s
found 0 vulnerabilities

Removing intermediate container 6ce3fed8ecd7
 ---> 38a27fea6567
Step 5/7 : EXPOSE 8080
 ---> Running in c7528a178327
Removing intermediate container c7528a178327
 ---> 97f454f32f95
Step 6/7 : CMD [ "npm", "start" ]
 ---> Running in 72a6340e3d58
Removing intermediate container 72a6340e3d58
 ---> 0a90efca7ea9
Step 7/7 : COPY . .
 ---> 84c4f69e2893
Successfully built 84c4f69e2893
Successfully tagged bulletinboard:1.0

将镜像作为容器运行

  1. 根据您的新镜像启动一个容器:
docker run --publish 8000:8080 --detach --name board bulletinboard:1.0

这里有几个常见的标志:

  • --publish要求 Docker 将主机端口 8000 上传入的流量转发到容器的端口 8080。容器具有自己的专用端口集,因此,如果要从网络访问某个端口,则必须以这种方式将流量转发到该端口。否则,作为默认的安全状态,防火墙规则将阻止所有网络流量到达您的容器。
  • --detach 要求 Docker 在后台运行此容器。
  • --name指定一个名称,您可以使用该名称在后续命令中引用您的容器,在这种情况下为board

还要注意,您没有指定容器要运行的程序。您不必这样做,因为在构建 Dockerfile 时使用了CMD指令。Docker 知道在容器启动时会自动运行npm start 程序。

  1. 在的浏览器中访问您的应用程序localhost:8000,您应该看到公告板应用程序已启动并正在运行。

公告板应用程序运行中

  1. 对公告板容器正常工作感到满意后,可以将其删除:
docker rm --force board

--force选项将删除正在运行的容器。如果停止容器运行,docker stop board则无需使用--force

相关文章

评论