Dockerfile 使用教程

什么是 Dockerfile?

Dockerfile 是一个用于构建 Docker 镜像的文本文件,里面包含了一系列指令,每条指令对应着镜像构建过程中的一个步骤。通过 Dockerfile 可以自动化地创建定制的镜像。

Dockerfile 基本结构

通常包含以下部分:

  • 基础镜像 (FROM)
  • 维护者信息 (LABELMAINTAINER)
  • 复制文件 (COPYADD)
  • 安装依赖 (RUN)
  • 配置环境变量 (ENV)
  • 工作目录 (WORKDIR)
  • 容器启动命令 (CMDENTRYPOINT)
  • 暴露端口 (EXPOSE)

示例 Dockerfile

下面是一个简单的 Dockerfile 示例,以 Python Flask 应用为例:

# 选择基础镜像
FROM python:3.9-slim

# 设置维护者信息
LABEL maintainer="yourname@example.com"

# 设置工作目录
WORKDIR /app

# 复制项目文件到容器
COPY . /app

# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt

# 设置环境变量
ENV FLASK_ENV=production

# 暴露端口
EXPOSE 5000

# 容器启动命令
CMD ["python", "app.py"]

常用指令介绍

  • FROM:指定基础镜像。
  • LABEL/MAINTAINER:镜像作者信息(推荐用 LABEL)。
  • WORKDIR:指定工作目录。
  • COPY:复制文件到容器。
  • ADD:类似 COPY,但支持解压和远程文件。
  • RUN:执行命令,比如安装依赖。
  • ENV:设置环境变量。
  • EXPOSE:声明端口。
  • CMD:容器启动时默认运行的命令(可被 docker run 覆盖)。
  • ENTRYPOINT:容器启动时执行的主命令(一般不被覆盖)。

构建镜像

在有 Dockerfile 的目录下执行:

docker build -t myapp:latest .

如果构建文件不叫Dockerfile,可以通过指定文件名的方式构建

docker build -f <你的文件名> -t myapp:latest .

构建mysql镜像举例(修改时区、增加构建人员信息、指定root密码和创建wp数据库)

[root@localhost mysql5.6]# ls
Dockerfile
[root@localhost mysql5.6]# cat Dockerfile 
FROM mysql:5.6
LABEL user=rufeike \
      email=rufeike@163.com
ENV TZ=Asia/Shanghai
ENV MYSQL_ROOT_PASSWORD=root
ENV MYSQL_DATABASE=wp
WORKDIR /var/lib/mysql
[root@localhost mysql5.6]# docker build -f Dockerfile -t wp-mysql:5.6 .
[+] Building 0.1s (6/6) FINISHED                                                                                                                                                                          docker:default
 => [internal] load build definition from Dockerfile                                                                                                                                                                0.0s
 => => transferring dockerfile: 258B                                                                                                                                                                                0.0s
 => [internal] load metadata for docker.io/library/mysql:5.6                                                                                                                                                        0.0s
 => [internal] load .dockerignore                                                                                                                                                                                   0.0s
 => => transferring context: 2B                                                                                                                                                                                     0.0s
 => [1/2] FROM docker.io/library/mysql:5.6                                                                                                                                                                          0.0s
 => [2/2] WORKDIR /var/lib/mysql                                                                                                                                                                                    0.0s
 => exporting to image                                                                                                                                                                                              0.0s
 => => exporting layers                                                                                                                                                                                             0.0s
 => => writing image sha256:02abd485c683b26f3bc38408c5ede5e8a9181ab56c2130a1219008558f73a5ea                                                                                                                        0.0s
 => => naming to docker.io/library/wp-mysql:5.6                                                                                                                                                                     0.0s
[root@localhost mysql5.6]# docker images
REPOSITORY               TAG       IMAGE ID       CREATED         SIZE
wp-mysql                 5.6       02abd485c683   6 seconds ago   303MB
nginx                    latest    07ccdb783875   5 days ago      160MB
tomcat                   latest    fb0c3b8680b7   5 days ago      412MB
portainer/portainer-ce   latest    e6b0d4bc3234   2 weeks ago     186MB
mysql                    8.0       94753e67a0a9   2 weeks ago     780MB
php                      8.2-fpm   0a9b59d0fded   2 months ago    490MB
mysql                    5.6       dd3b2a5dcb48   3 years ago     303MB
[root@localhost mysql5.6]# docker run -d --name=wp-mysql -p 3306:3306 \
> -v /root/docker-volumn/mysql/data:/var/lib/mysql \
> wp-mysql:5.6
b21d2f8f64cfcc71519742d82663fea9808530bce9bd0cdadb55787233aad52a
[root@localhost mysql5.6]# docker ps
CONTAINER ID   IMAGE                           COMMAND                   CREATED         STATUS             PORTS                                                                                            NAMES
b21d2f8f64cf   wp-mysql:5.6                    "docker-entrypoint.s…"   5 seconds ago   Up 4 seconds       0.0.0.0:3306->3306/tcp, :::3306->3306/tcp                                                        wp-mysql
4e61e24b45f4   tomcat:latest                   "catalina.sh run"         2 hours ago     Up About an hour   0.0.0.0:8081->8080/tcp, :::8081->8080/tcp                                                        tomcat-8081
7c5f40cc8c19   nginx:latest                    "/docker-entrypoint.…"   2 hours ago     Up About an hour   0.0.0.0:80->80/tcp, :::80->80/tcp                                                                nginx-80
cfef42dae016   tomcat:latest                   "catalina.sh run"         2 hours ago     Up About an hour   0.0.0.0:8082->8080/tcp, :::8082->8080/tcp                                                        tomcat-8082
c324bd691d04   tomcat:latest                   "catalina.sh run"         2 hours ago     Up About an hour   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp                                                        tomcat-8080
e098f5ecc088   portainer/portainer-ce:latest   "/portainer"              2 hours ago     Up About an hour   0.0.0.0:8000->8000/tcp, :::8000->8000/tcp, 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp, 9443/tcp   portainer


运行容器

构建完镜像后可以用以下命令运行:

docker run -d -p 5000:5000 myapp:latest

常见问题

  • 缓存问题:每个指令都会生成一层缓存,合理排序指令可以提高构建效率。
  • 权限问题:有时需要在 RUN 指令里加 sudo 或切换用户。
  • 多阶段构建:可以用多个 FROM,用于编译和最终镜像分离,减小镜像体积。

实用案例

1. Node.js Web 项目

FROM node:18

WORKDIR /usr/src/app

COPY package*.json ./
RUN npm install --production

COPY . .

EXPOSE 3000
CMD ["node", "server.js"]

说明:此镜像用于部署 Node.js 应用,使用官方 node 镜像,安装依赖后运行主程序。

2. 构建静态网页(Nginx)

FROM nginx:alpine

COPY dist/ /usr/share/nginx/html

EXPOSE 80

说明:将前端打包好的 dist 文件夹直接复制到 Nginx 默认网页目录,可用于静态网站部署。

3. 多阶段构建(Go 编译)

# 构建阶段
FROM golang:1.20-alpine AS builder

WORKDIR /app
COPY . .
RUN go build -o myapp

# 运行阶段
FROM alpine:latest

WORKDIR /root/
COPY --from=builder /app/myapp .

EXPOSE 8080
CMD ["./myapp"]

说明:多阶段构建用于编译 Go 项目后,使用更小的镜像运行编译好的二进制文件,节省空间。

4. 自定义环境变量和入口

FROM ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y nginx
EXPOSE 80

ENTRYPOINT ["nginx", "-g", "daemon off;"]

说明:设置环境变量,安装 Nginx 并保持前台运行。

参考资料


制作Wordpress 镜像

制作前准备

  • 下载Wordpress文件
    https://wordpress.org/download/

  • 解压安装压缩包,拷贝wp-config-sample.php文件,并命名为wp-config.php

  • 修改相关配置文件的配置参数

<?php
/**
 * The base configuration for WordPress
 *
 * The wp-config.php creation script uses this file during the installation.
 * You don't have to use the website, you can copy this file to "wp-config.php"
 * and fill in the values.
 *
 * This file contains the following configurations:
 *
 * * Database settings
 * * Secret keys
 * * Database table prefix
 * * ABSPATH
 *
 * @link https://developer.wordpress.org/advanced-administration/wordpress/wp-config/
 *
 * @package WordPress
 */

// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'database_name_here' );

/** Database username */
define( 'DB_USER', 'username_here' );

/** Database password */
define( 'DB_PASSWORD', 'password_here' );

/** Database hostname */
define( 'DB_HOST', 'localhost' );

/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );

/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );

/**#@+
 * Authentication unique keys and salts.
 *
 * Change these to different unique phrases! You can generate these using
 * the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}.
 *
 * You can change these at any point in time to invalidate all existing cookies.
 * This will force all users to have to log in again.
 *
 * @since 2.6.0
 */
define('AUTH_KEY',         'T|oyi =-~([@zb)ERp9z}]avj3{$eBJ$A3}`g0(Xy(vQ,}N~=u,@e~?(gwIJQ.o1');
define('SECURE_AUTH_KEY',  'PyHyV|sQ,ofAA-r@&O*RQ7<TrELW+5k5f?Iz:9HP*>Pj79y$#0q:u-~u^c:1sHYE');
define('LOGGED_IN_KEY',    '|ab+ADSU7L-|+jn11KVb3|w0DIep/eWq#?wn) 4o,y{y`YD|{fO$yJ`FxZR66KOJ');
define('NONCE_KEY',        '?e;|X&<h.!f,lbA[#HU6@odkVH5T@sl44d*wUg]u(S~;vTJ.s/tQ0]` K/F!jbDT');
define('AUTH_SALT',        '>; FuHWT]i~E>f$rFZjkli=rctm+[gSYn#{TYtyb4b0was6Q[45V++Q[c<H=W|ya');
define('SECURE_AUTH_SALT', '0rx=l5=FBSzLpy_`82LpU0T[|6,|1H|YWo[ODDv_P =M|8%~:bbr45*_Zay[kZ:=');
define('LOGGED_IN_SALT',   'o#Af^=Vf[u=Hm 6YtS!^QeTu{ai:8~B8=,aI9.v?gPy@nuLar@|+RMI+}o*,Ae4S');
define('NONCE_SALT',       '6&S{a*WzFx-_~a?VdKvGuN@e%eG748E8VXc?b/.ha>iT)i|d!zq>v+bWI{1{?=%x');

/**#@-*/

/**
 * WordPress database table prefix.
 *
 * You can have multiple installations in one database if you give each
 * a unique prefix. Only numbers, letters, and underscores please!
 *
 * At the installation time, database tables are created with the specified prefix.
 * Changing this value after WordPress is installed will make your site think
 * it has not been installed.
 *
 * @link https://developer.wordpress.org/advanced-administration/wordpress/wp-config/#table-prefix
 */
$table_prefix = 'wp_';

/**
 * For developers: WordPress debugging mode.
 *
 * Change this to true to enable the display of notices during development.
 * It is strongly recommended that plugin and theme developers use WP_DEBUG
 * in their development environments.
 *
 * For information on other constants that can be used for debugging,
 * visit the documentation.
 *
 * @link https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/
 */
define( 'WP_DEBUG', false );

/* Add any custom values between this line and the "stop editing" line. */



/* That's all, stop editing! Happy publishing. */

/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
	define( 'ABSPATH', __DIR__ . '/' );
}

/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';

注意事项

制作nginx镜像源仓库

根据不同安装系统,选择对应的镜像源,被教程准备制作的镜像基础系统为lockylinux(centos替代系统),所以使用一下镜像源
nginx官方安装镜像源仓库
在Wordpress的解压文件夹中创建nginx.repo文件,写入一下内容。

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

在这里插入图片描述

Nginx 配置 WordPress 站点配置文件

在Wordpress解压文件中,创建一个wordpress.conf配置文件

server {
    listen 80;
    server_name localhost;
    
    # 允许最大上传文件大小
    client_max_body_size 100M;
    root /usr/share/nginx/html; # nginx站点目录
    index index.php index.html index.htm;

    # 主要 WordPress rewrite 规则
    location / {
    		 try_files $uri $uri/ /index.php?$args;
    }

    # 处理 PHP 文件
    location ~ [^/]\.php(/|$) {
    			include fastcgi_params;
			fastcgi_pass unix:/run/php-fpm/www.sock; # 或者 fastcgi_pass 127.0.0.1:9000;
			fastcgi_index index.php;
			fastcgi_param DOCUMENT_ROOT /usr/share/nginx/html;
			fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
			fastcgi_param PATH_TRANSLATED  /usr/share/nginx/html$fastcgi_script_name;
			fastcgi_param SCRIPT_NAME $fastcgi_script_name;
    }

    # 禁止访问 .htaccess 等隐藏文件
    location ~ /\. {
        deny all;
    }

    # 静态文件缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        try_files $uri =404;
    }


    # WordPress 核心文件
    location ~ ^/(wp-includes)/ {
        try_files $uri =404;
    }
}

注意事项

  • server_name 请替换为你的实际域名。
  • root 路径设为你的 WordPress 安装目录。
  • fastcgi_pass 需与你实际的 PHP-FPM 配置一致。常见为 unix socket 或 127.0.0.1:9000。
  • 若用 HTTPS,可在此基础上添加 SSL 相关配置。
参考资料

Dockerfile文件编写

Dockerfile

# 与rockylinux:9.0作为基础版本
FROM rockylinux:9.0

# 调整镜像时区
ENV TZ=Asia/Shanghai

# 拷贝Nginx仓库文件
COPY ./nginx.repo /etc/yum.repos.d/

# 安装Wordpress运行环境LNMP
RUN dnf install -y nginx-1.20.2 php php-fpm php-mysqlnd php-gd freetype-devel libjpeg-turbo-devel \
    && dnf clean all

# 准备Wordpress站点配置文件
RUN rm -rf /etc/nginx/conf.d/default.conf
COPY ./wordpress.conf /etc/nginx/conf.d/

# 拷贝网页文件到Nginx网页目录
COPY . /usr/share/nginx/html/

# 删除多余的文件
RUN rm -rf /usr/share/nginx/html/wordpress.conf \
    && rm -rf /usr/share/nginx/html/nginx.repo

# 修改php运行的用户和组 网页文件权限
RUN sed -i 's/user = apache/user = nginx/' /etc/php-fpm.d/www.conf \
    && sed -i 's/group = apache/group = nginx/' /etc/php-fpm.d/www.conf \
    && sed -i 's#;date.timezone =#date.timezone = Asia/Shanghai#' /etc/php.ini \
    && chown -R nginx.nginx /usr/share/nginx/html/ \
    && mkdir /run/php-fpm

# 暴露容器端口
EXPOSE 80

# 启动命令 (若启动命令比较多,可以用ENTRPOINT 启动脚本的方式执行)
CMD /usr/sbin/php-fpm && /usr/sbin/nginx  -g "daemon off;"

注意事项

  • 容器启动时,必须容器内部有一个前台运行的程序,否则无法启动。如下,把nginx启动命令后面,补充-g "daemon off;"关闭后台运行的参数
    在这里插入图片描述

  • Dockerfile文件中的安装指令,必须增加-y,自动同意安装过程,否则镜像制作时,会终止
    在这里插入图片描述

开启制作镜像

启动构建命令
# 进入Dockerfile文件所在目录
docker build -f Dockerfile -t wp:v1.0 .

在这里插入图片描述

如果没有报错,可以在Docker镜像列表中查看到
docker images

在这里插入图片描述

创建容器,启动验证效果
docker run -d --name=wordpress -p 80:80  wp:v1.0

在这里插入图片描述
在这里插入图片描述

注意事项
  • 制作镜像,启动容器后,出现一下报错
[root@localhost docker-volumn]# docker logs wordpress
[14-Oct-2025 10:54:14] ERROR: unable to bind listening socket for address '/run/php-fpm/www.sock': No such file or directory (2)
[14-Oct-2025 10:54:14] ERROR: FPM initialization failed

在这里插入图片描述

  • 需要再Dockerfile 中补充创建/run/php-fpm目录

在这里插入图片描述

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐