Dockerfile 是 Docker 的核心功能之一,通过它我们能够自动化地构建自定义镜像。在这一章,我们将深入探讨 Dockerfile 的基本语法和使用方法,并通过实际案例展示如何构建自定义镜像。

1. Dockerfile 基础

什么是 Dockerfile

Dockerfile 是一个文本文件,其中包含了一系列的指令,这些指令定义了一个 Docker 镜像的构建过程。每个指令对应一个镜像层,最终形成一个可以执行的 Docker 镜像。

Dockerfile 的基本语法

Dockerfile 的基本语法相对简单,但它具有很强的表达能力。下面是一些常用的指令:

  • FROM:指定基础镜像
  • RUN:执行命令
  • COPYADD:复制文件到镜像中
  • CMDENTRYPOINT:指定容器启动时的命令
  • EXPOSE:暴露端口
  • ENV:设置环境变量
  • WORKDIR:设置工作目录

编写第一个 Dockerfile

我们将编写一个简单的 Dockerfile 来构建一个包含 Node.js 环境的镜像。

  1. # 使用官方的 Node.js 镜像作为基础镜像
  2. FROM node:14
  3. # 创建并设置工作目录
  4. WORKDIR /app
  5. # 复制 package.json 和 package-lock.json
  6. COPY package*.json ./
  7. # 安装依赖
  8. RUN npm install
  9. # 复制应用代码
  10. COPY . .
  11. # 暴露应用端口
  12. EXPOSE 8080
  13. # 启动应用
  14. CMD ["node", "app.js"]

以上 Dockerfile 文件定义了一个以 Node.js 镜像为基础的自定义镜像,它将应用代码复制到镜像中并安装所需的依赖,最后设置启动命令。

2. 构建自定义镜像

使用 docker build 构建镜像

使用 docker build 命令可以根据 Dockerfile 构建镜像。以下是其基本用法:

  1. docker build -t my-node-app .

参数解释:

  • -t my-node-app:为镜像指定标签 my-node-app
  • .:指定 Dockerfile 的路径(当前目录)

多阶段构建

多阶段构建是一种优化镜像大小的方法,通过在构建过程中使用多个 FROM 指令,可以有效减少最终镜像的体积。

  1. # 第一阶段:构建阶段
  2. FROM node:14 AS builder
  3. WORKDIR /app
  4. COPY package*.json ./
  5. RUN npm install
  6. COPY . .
  7. RUN npm run build
  8. # 第二阶段:生产阶段
  9. FROM node:14
  10. WORKDIR /app
  11. COPY --from=builder /app/dist ./dist
  12. COPY --from=builder /app/node_modules ./node_modules
  13. EXPOSE 8080
  14. CMD ["node", "dist/app.js"]

上述 Dockerfile 分为两个阶段:

  1. 构建阶段:编译代码,生成构建产物
  2. 生产阶段:仅复制构建产物,大大减小了镜像体积

镜像优化与缓存机制

Docker 在构建镜像时使用分层缓存机制,可以加速构建过程。为了充分利用缓存机制,我们应尽量将不经常变化的指令放在 Dockerfile 的前面。

3. Dockerfile 实践

使用 Dockerfile 构建 Web 应用镜像

我们将构建一个简单的 Node.js Web 应用镜像。

  1. 创建项目目录并初始化 Node.js 项目:
  1. mkdir my-web-app
  2. cd my-web-app
  3. npm init -y
  1. 安装 Express:
  1. npm install express
  1. 创建 app.js 文件:
  1. const express = require("express");
  2. const app = express();
  3. const port = 8080;
  4. app.get("/", (req, res) => {
  5. res.send("Hello, Docker!");
  6. });
  7. app.listen(port, () => {
  8. console.log(`App running at http://localhost:${port}`);
  9. });
  1. 编写 Dockerfile:
  1. FROM node:14
  2. WORKDIR /app
  3. COPY package*.json ./
  4. RUN npm install
  5. COPY . .
  6. EXPOSE 8080
  7. CMD ["node", "app.js"]
  1. 构建镜像并运行容器:
  1. docker build -t my-web-app .
  2. docker run -p 8080:8080 my-web-app

访问 http://localhost:8080,你将看到 “Hello, Docker!”。

使用 Dockerfile 构建数据库镜像

我们将使用官方的 MySQL 镜像并进行一些自定义配置。

  1. 创建 Dockerfile:
  1. FROM mysql:5.7
  2. ENV MYSQL_ROOT_PASSWORD=my-secret-pw
  3. ENV MYSQL_DATABASE=mydatabase
  4. COPY ./init.sql /docker-entrypoint-initdb.d/
  1. 创建 init.sql 文件,以初始化数据库:
  1. CREATE TABLE users (
  2. id INT AUTO_INCREMENT PRIMARY KEY,
  3. name VARCHAR(255) NOT NULL
  4. );
  1. 构建镜像并运行容器:
  1. docker build -t my-mysql .
  2. docker run -d -p 3306:3306 --name my-mysql-container my-mysql

通过这些示例,你可以学会如何使用 Dockerfile 构建和自定义各种类型的应用镜像。