Dockerfiles
Dockerfile 可用于自动创建 Docker
容器图像。
让我们从为一个简单的 Node.js 程序构建一个应用程序映像开始。这个示例对于
许多其他动态语言(如 Python 或 Ruby)来说非常相似。
最简单的 npm/Node/Express 应用程序有两个文件: package.json (示
例 2‑1)和server.js (示例 2‑2)。将这些放在一个目录中,然后运行 npm install
express ‑‑save 来建立一个对 Express 的依赖并安装它。
{
“name”: “simple-node”,
“version”: “1.0.0”,
“description”: “A sample simple application for Kubernetes Up
& Running”,
“main”: “server.js”,
“scripts”: {
“start”: “node server.js”
},
“author”: “”
}
var express = require(‘express’);
var app = express();
app.get(‘/’, function (req, res) {
res.send(‘Hello World!’);
});
app.listen(3000, function () {
console.log(‘Listening on port 3000!’);
console.log(‘ http://localhost:3000’);
});
要将其打包为 Docker 映像,我们需要创建两个附加文件: .dockerignore 和 Dockerfile
dockerignore
node_modules
这是 Dockerfile 中 COPY 和 ADD 命令中忽略的文件或文件夹列表,这些文件或文件夹将不会被复制到 Docker 镜像中。在这个例子中,“.dockerignore” 文件列出了 “node_modules” 文件夹,因此 Docker 在构建镜像时将不会复制 “node_modules” 文件夹到镜像中,这样可以减小镜像的大小,加快构建速度
# Start from a Node.js 10 (LTS) image
FROM node:10
每个 Dockerfile 都建立在其他容器镜像之上。此行指定我们从 Docker Hub 上的 node:10 映像开始。这是使用 Node.js 10 的预配置图像。
指定 Dockerfile 基础镜像,这里使用了 Node.js 10 LTS 版本的镜像;
# Specify the directory inside the image in which all commands
will run
WORKDIR /usr/src/app
此行在容器映像中为所有后续命令设置工作目录。
指定在镜像中运行命令时的工作目录为 /usr/src/app;
# Copy package files and install dependencies
COPY package*.json ./
RUN npm install
复制 package.json 和 package-lock.json(如果存在)到镜像的工作目录,然后运行 npm install 命令来安装 Node.js 应用程序的依赖;
这两行初始化 Node.js 的依赖项。首先我们将包文件复制到镜像中。这将包括package.json和package‑lock.json。 RUN 命令然后在容器中运行正确的命令以安装必要的依赖项。
# Copy all of the app files into the image
COPY . .
将应用程序的所有文件复制到镜像的工作目录中;
现在我们将其余的程序文件复制到映像中。这将包括除node_modules 之外的所有内容,因为它通过.dockerignore文件排除。
# The default command to run when starting the container
CMD [ “npm”, “start” ]
指定容器启动时默认运行的命令,即执行 npm start 命令启动 Node.js 应用程序。
最后,我们指定容器运行时应运行的命令
CONTAINER LAYERING
The phrases “Docker image format” and “container images” may be a bit confusing. The image isn’t a
single file but rather a specification for a manifest file that points to other files. The manifest and
associated files are often treated by users as a unit. The level of indirection allows for more efficient
storage and transmittal. Associated with this format is an API for uploading and downloading images
to an image registry.
Container images are constructed with a series of filesystem layers, where each layer inherits and
modifies the layers that came before it. To help explain this in detail, let’s build some containers. Note
that for correctness the ordering of the layers should be bottom up, but for ease of understanding we
take the opposite approach:
.
└── container A: a base operating system only, such as Debian└── container B: build upon #A, by adding Ruby v2.1.10
└── container C: build upon #A, by adding Golang v1.6
At this point we have three containers: A, B, and C. B and C are forked from A and share nothing
besides the base container’s files. Taking it further, we can build on top of B by adding Rails (version
4.2.6). We may also want to support a legacy application that requires an older version of Rails (e.g.,
version 3.2.x). We can build a container image to support that application based on B also, planning to
someday migrate the app to version 4:
. (continuing from above)
└── container B: build upon #A, by adding Ruby v2.1.10
└── container D: build upon #B, by adding Rails v4.2.6
└── container E: build upon #B, by adding Rails v3.2.x
Conceptually, each container image layer builds upon a previous one. Each parent reference is a
pointer. While the example here is a simple set of containers, other real-world containers can be part
of a larger extensive directed acyclic graph.
这是一个简单的 Docker 容器层次结构示例,包含了多个容器(Container)以及它们之间的关系。容器是 Docker 技术中的核心概念之一,用于隔离应用程序或服务所需的运行时环境。
在这个示例中,有一个名为 A 的基础操作系统容器,上面构建了 B 和 C 两个容器。容器 B 在 A 的基础上添加了 Ruby v2.1.10 运行环境,而容器 C 则添加了 Golang v1.6 运行环境。容器 D 建立在容器 B 的基础上,并添加了 Rails v4.2.6 框架。最后,容器 E 建立在容器 B 的基础上,并添加了 Rails v3.2.x 框架。
这种容器层次结构可以方便地管理应用程序的依赖关系和版本控制,同时也可以提高应用程序的可移植性和安全性。