Dockerfile实战案例详解
一、课程概述
本课程围绕Dockerfile的实际应用展开,通过三个典型案例------构建Nginx镜像 、部署扫雷游戏 、搭建可道云平台,帮助学习者掌握从基础镜像定制到应用容器化部署的完整流程。每个案例均包含环境准备、Dockerfile编写、镜像构建、容器运行及验证等关键步骤,覆盖Dockerfile核心指令(FROM、ADD、RUN、EXPOSE、CMD、ENTRYPOINT等)的使用场景,同时结合实际运维需求(如自定义配置文件、初始化脚本编写、端口映射等),确保案例的实用性与可操作性。
二、案例一:Dockerfile构建Nginx镜像
Nginx是常用的高性能HTTP服务器与反向代理服务器,本案例基于CentOS 7基础镜像,通过Dockerfile定制包含Nginx服务的镜像,并实现容器化运行与访问验证。
2.1 环境准备
- 基础镜像:CentOS 7(官方维护的稳定版本,适合企业级应用环境)。
- 依赖文件 :
Centos-7.repo
:CentOS 7官方YUM源配置文件,用于解决基础镜像中YUM源失效或速度慢的问题。epel-7.repo
:EPEL(Extra Packages for Enterprise Linux)源配置文件,提供CentOS官方源中未包含的额外软件包(如Nginx)。
- 操作主机 :已安装Docker Engine的Linux主机(本案例中主机名为
docker
,后续命令均基于此主机执行)。
2.2 Dockerfile编写
创建并编辑vim Dockerfile,指令含义与作用如下表所示:
指令 | 具体内容 | 功能说明 |
---|---|---|
FROM | centos:7 |
指定基础镜像为CentOS 7,所有后续操作均基于此镜像层构建 |
MAINTAINER | ycy@example.com |
声明镜像维护者信息(邮箱),便于后续镜像管理与问题追溯 |
ADD | Centos-7.repo /etc/yum.repos.d/ |
将本地的Centos-7.repo 文件复制到容器内的/etc/yum.repos.d/ 目录(覆盖默认源),ADD指令支持自动解压压缩文件,但本案例中用于普通文件复制 |
ADD | epel-7.repo /etc/yum.repos.d/ |
同理,将本地的epel-7.repo 文件复制到容器内YUM源目录,为安装Nginx提供依赖源 |
RUN | yum -y install nginx |
在容器内执行YUM安装命令,-y 参数自动确认所有安装提示,避免交互阻塞,最终在容器内安装Nginx服务 |
EXPOSE | 80 |
声明容器对外暴露的端口为80(Nginx默认HTTP端口),仅为"声明"作用,不实际映射端口,需在docker run 时通过-p 参数实现端口映射 |
CMD | ["/usr/sbin/nginx","-g","daemon off;"] |
容器启动时执行的命令,启动Nginx服务并指定daemon off; (禁止Nginx以守护进程模式运行)。由于Docker容器启动后需保持前台进程运行,若Nginx以守护进程模式启动,容器会因无前台进程而立即退出 |
完整Dockerfile编写命令:
bash
[root@docker ~]# vim Dockerfile
# 粘贴上述指令内容,保存并退出(vim中按Esc,输入:wq)
FROM centos:7
RUN rm -rf /etc/yum.repos.d/*
ADD Centos-7.repo /etc/yum.repos.d/
ADD epel-7.repo /etc/yum.repos.d/
RUN yum -y install nginx
EXPOSE 80
CMD ["/usr/sbin/nginx","-g","daemon off;"]
2.3 镜像构建与容器运行
2.3.1 构建Nginx镜像
在Dockerfile所在目录执行docker build
命令,构建标签为nginx:v1
的镜像:
bash
[root@docker ~]# docker build -t nginx:v1 .
# -t nginx:v1:为镜像添加标签(名称:版本),便于识别与管理
# .(点):指定Dockerfile所在的上下文目录(当前目录),Docker会将该目录下所有文件发送到Docker daemon用于构建
构建过程中,Docker会按Dockerfile指令逐行执行,输出每一步的日志(如基础镜像拉取、YUM安装依赖、文件复制等),最终提示"Successfully built <镜像ID>"表示构建成功。
2.3.2 运行Nginx容器
通过docker run
命令启动容器,并将主机的88端口映射到容器的80端口(避免与主机已有的80端口冲突):
bash
[root@docker ~]# docker run -itd -p 88:80 --name nginx nginx:v1
# 输出示例:949990a5d00de424084e5a169e03faf3f76cfd0baf626e97d9f1b1ec2ef8858a(容器ID)
# 说明:
# -d:后台运行容器(守护进程模式)
# -p 88:80:端口映射,格式为"主机端口:容器端口",外部可通过主机IP:88访问容器内的Nginx服务
2.4 容器验证与页面自定义
2.4.1 查看容器运行状态
通过docker ps
命令确认容器是否正常运行:
bash
[root@docker ~]# docker ps
# 输出结果(关键列说明):
# CONTAINER ID:容器唯一ID(如949990a5d00d)
# IMAGE:使用的镜像(nginx:v1)
# COMMAND:容器启动命令(/usr/sbin/nginx -g daemon off;)
# STATUS:运行状态(Up 1 second,表示已运行1秒)
# PORTS:端口映射关系(0.0.0.0:88->80/tcp,表示主机88端口映射到容器80端口)
# NAMES:容器名称(confident_bell,Docker自动生成,可通过--name参数自定义)
2.4.2 进入容器自定义Nginx首页
默认Nginx首页位于容器内的/usr/share/nginx/html/index.html
,可进入容器修改该文件内容:
-
进入运行中的容器(通过容器ID或名称):
bash[root@docker ~]# docker exec -it 949990a5d00d /bin/bash # 说明: # -it:以交互模式进入容器,并分配伪终端(可执行命令) # /bin/bash:指定进入容器后执行的Shell(CentOS 7默认Shell为bash)
-
进入Nginx网页根目录并修改首页:
bash[root@949990a5d00d /]# cd /usr/share/nginx/ # 进入Nginx安装目录 [root@949990a5d00d nginx]# ls # 查看目录内容,输出html(网页根目录)、modules(Nginx模块目录) [root@949990a5d00d nginx]# cd html/ # 进入网页根目录 [root@949990a5d00d html]# ls # 查看默认文件(404.html、50x.html、index.html等) [root@949990a5d00d html]# rm -rf index.html # 删除默认首页 [root@949990a5d00d html]# echo abc > index.html # 创建新首页,内容为"abc" [root@949990a5d00d html]# exit # 退出容器
2.4.3 浏览器访问验证
在本地浏览器输入http://192.168.100.10:88
(其中192.168.100.10
为Docker主机IP),页面显示"abc",表示Nginx容器运行正常且首页自定义成功。
三、案例二:Dockerfile部署扫雷游戏(基于Tomcat)
扫雷游戏为Java Web应用(JSP),需基于Tomcat服务器运行。本案例通过Dockerfile构建包含Tomcat与扫雷游戏的镜像,实现游戏的容器化部署。
3.1 环境准备
- 基础镜像:CentOS 7(与案例一一致,保证环境一致性)。
- 依赖文件与工具 :
Centos-7.repo
、epel-7.repo
:同案例一,用于YUM源配置。saolei.zip
:扫雷游戏的Web应用压缩包(包含JSP、CSS、JS等文件)。- 本地Apache服务 :在Docker主机上部署Apache(httpd),用于提供
saolei.zip
的下载服务(容器构建时通过HTTP拉取该压缩包)。
- 核心软件:Tomcat(Java Web服务器)、unzip(解压压缩包)、curl(HTTP下载工具)。
3.2 方法一:
步骤1:Docker主机部署Apache服务(提供游戏包下载)
由于容器构建时需获取saolei.zip
,需先在Docker主机上通过Apache服务暴露该文件的下载地址:
-
安装Apache服务(httpd):
bash[root@docker ~]# yum -y install httpd
-
上传依赖文件到
/root
目录:bash[root@docker ~]# ls /root/ # 确认文件存在,输出Centos-7.repo、epel-7.repo
-
放置扫雷游戏压缩包到Apache网页根目录:
bash[root@docker ~]# cp saolei.zip /var/www/html/ # Apache默认网页根目录为/var/www/html [root@docker ~]# ls /var/www/html/ # 确认文件,输出index.html(Apache默认首页)、saolei.zip
-
启动并设置Apache开机自启:
bash[root@docker ~]# systemctl restart httpd # 重启Apache服务 [root@docker ~]# systemctl enable httpd # 设置开机自启(避免主机重启后服务失效)
-
验证Apache服务:在浏览器输入
http://192.168.100.10/saolei.zip
,可正常下载文件,说明Apache服务配置成功。
3.3 步骤2:编写Dockerfile与初始化脚本
3.3.1 Dockerfile编写
创建Dockerfile,指令功能如下表所示:
指令 | 具体内容 | 功能说明 |
---|---|---|
FROM | centos:7 |
基础镜像,同前序案例 |
MAINTAINER | ycy@example.com |
镜像维护者信息 |
ADD | Centos-7.repo /etc/yum.repos.d/ 、epel-7.repo /etc/yum.repos.d/ |
配置YUM源,同案例一 |
RUN | yum -y install tomcat unzip curl |
安装Tomcat(Java Web服务器)、unzip(解压saolei.zip)、curl(下载saolei.zip) |
WORKDIR | /var/lib/tomcat/webapps/ |
设置容器内的工作目录(后续命令均在此目录执行),Tomcat默认Web应用部署目录为/var/lib/tomcat/webapps/ |
RUN | curl -O http://192.168.100.10/saolei.zip && unzip saolei.zip && mv saolei ROOT |
1. curl -O :从Apache服务下载saolei.zip到当前工作目录; 2. unzip saolei.zip :解压压缩包,生成saolei 目录(包含游戏代码); 3. mv saolei ROOT :将saolei 目录重命名为ROOT (Tomcat默认访问的根应用目录,避免访问时需加路径/saolei ) |
ADD | init.sh /init.sh |
将本地的初始化脚本init.sh 复制到容器内的/ 目录 |
EXPOSE | 8080 |
声明容器暴露端口(Tomcat默认HTTP端口为8080) |
CMD | ["bin/bash","/init.sh"] |
容器启动时执行/init.sh 脚本(用于启动Tomcat服务) |
Dockerfile编写命令:
bash
[root@docker ~]# vim Dockerfile
# 粘贴上述指令,保存退出
3.3.2 编写初始化脚本init.sh
Tomcat启动命令需在前台执行(避免容器退出),通过init.sh
脚本封装启动逻辑:
-
创建并编辑
init.sh
:bash[root@docker ~]# vim init.sh
-
写入脚本内容(启动Tomcat服务):
bash#!/bin/bash # Tomcat启动命令(CentOS 7中Tomcat启动脚本路径为/usr/libexec/tomcat/server) /usr/libexec/tomcat/server start # 说明:Tomcat的`server start`命令默认会保持前台运行(与Nginx的`daemon off;`作用一致),确保容器不退出
-
赋予脚本执行权限(关键步骤,否则容器启动时脚本无法运行):
bash[root@docker ~]# chmod +x init.sh
3.4 步骤3:镜像构建与容器运行
3.4.1 构建扫雷游戏镜像
bash
[root@docker ~]# docker build -t saolei:v1 .
# -t saolei:v1:镜像标签(名称:版本),便于识别
构建成功后,通过docker images
可查看saolei:v1
镜像。
3.4.2 运行扫雷游戏容器
使用-P
参数(大写)让Docker自动映射容器暴露的8080端口到主机的随机端口(避免端口冲突),并指定容器名称为saolei
:
bash
[root@docker ~]# docker run -itd --name saolei -P saolei:v1
# 输出示例:8ab87465634a8709d1a335ffb5c4f3fb83ea0d33cb25ff684c818fffb8e6df18(容器ID)
# 说明:
# --name saolei:自定义容器名称,后续可通过名称操作容器(如docker stop saolei)
# -P(大写):自动映射容器EXPOSE声明的端口到主机的随机端口(范围通常为32768-61000)
3.4.3 查看端口映射与访问游戏
-
查看容器的端口映射关系:
bash[root@docker ~]# docker ps # 查看PORTS列,示例输出:0.0.0.0:32770->8080/tcp(主机32770端口映射到容器8080端口)
-
浏览器访问:输入
http://192.168.100.10:32770/saolei.jsp
(主机IP+自动映射的端口),进入扫雷游戏页面,选择"初级"即可开始游戏,验证部署成功。
方法二:直接把扫雷 的包文件上传到本地目录
bash
vim Dockerfile
bash
FROM centos:7
RUN rm -rf /etc/yum.repos.d/*
ADD Centos-7.repo /etc/yum.repos.d/
ADD epel-7.repo /etc/yum.repos.d/
RUN yum -y install tomcat unzip
WORKDIR /var/lib/tomcat/webapps/
ADD saolei.zip .
RUN unzip saolei.zip && mv saolei ROOT
ADD init.sh /init.sh
EXPOSE 8080
CMD ["/bin/bash","/init.sh"]
四、案例三:Dockerfile搭建可道云平台(基于Nginx+PHP)
可道云(KodExplorer)是一款在线文件管理系统,需Nginx(Web服务器)+PHP(动态语言解析)环境支持。本案例通过Dockerfile构建包含Nginx、PHP-FPM及可道云的镜像,实现平台的容器化部署。
4.1 环境准备
- 基础镜像:CentOS 7(保证与前序案例环境一致)。
- 依赖文件 :
Centos-7.repo
、epel-7.repo
:YUM源配置文件,同前序案例。kodexplorer4.40.zip
:可道云的Web应用压缩包(包含PHP、HTML、JS等文件)。nginx.conf
:自定义Nginx配置文件(配置PHP解析、网页根目录等)。
- 核心软件:Nginx(Web服务器)、PHP-FPM(PHP FastCGI进程管理器,用于解析PHP脚本)、PHP扩展(php-gd、php-mbstring,可道云依赖)、unzip(解压压缩包)。
4.2 步骤1:目录结构与文件准备
为便于管理Dockerfile及相关依赖文件,先在Docker主机上创建专用目录:
bash
[root@docker ~]# cd /opt # 进入/opt目录(常用于存放第三方应用)
[root@docker opt]# mkdir dockerfile # 创建dockerfile总目录
[root@docker opt]# cd dockerfile
[root@docker dockerfile]# mkdir kod # 创建可道云案例的专用目录
[root@docker dockerfile]# cd kod # 进入kod目录(后续所有操作均在此目录执行)
[root@docker kod]# ls # 确认目录内文件,输出dockerfile(待创建)、Centos-7.repo Dockerfile epel-7.repo init.sh kodexplorer4.40.zip nginx.conf
4.3 步骤2:自定义Nginx配置文件(nginx.conf)
可道云为PHP应用,需配置Nginx将PHP请求转发给PHP-FPM处理。nginx.conf
完整内容及说明如下:
nginx
# 1. 全局配置:Nginx工作进程数(通常设为CPU核心数,此处简化为1)
worker_processes 1;
# 2. 事件模块配置:每个工作进程的最大连接数
events {
worker_connections 1024;
}
# 3. HTTP模块配置:处理HTTP请求的核心配置
http {
include mime.types; # 引入MIME类型映射文件(识别不同文件类型,如.html、.php)
default_type application/octet-stream; # 默认MIME类型(未识别文件按二进制流处理)
sendfile on; # 开启高效文件传输模式(减少IO开销)
keepalive_timeout 65; # 客户端连接超时时间(65秒,避免无效连接占用资源)
# 4. 虚拟主机配置(单个站点配置)
server {
listen 80; # 监听80端口(HTTP默认端口)
server_name localhost; # 站点域名(此处为localhost,可改为实际域名)
# 5. 静态资源处理:匹配所有请求,指定网页根目录
location / {
root /code; # 可道云应用的根目录(容器内路径,后续会创建)
index index.php index.html index.htm; # 默认索引文件(优先解析index.php)
}
# 6. PHP请求处理:匹配以.php结尾的请求,转发给PHP-FPM
location ~ \.php$ {
root /code; # PHP文件所在的根目录(与静态资源根目录一致)
fastcgi_pass 127.0.0.1:9000; # 转发PHP请求到PHP-FPM的监听地址(127.0.0.1:9000)
fastcgi_index index.php; # PHP默认索引文件
# 配置PHP脚本的真实路径(告诉PHP-FPM脚本在容器内的位置)
fastcgi_param SCRIPT_FILENAME /code$fastcgi_script_name;
include fastcgi_params; # 引入FastCGI通用参数配置
}
}
}
文件验证:
bash
[root@docker kod]# cat nginx.conf # 查看配置文件内容,确认与上述一致
4.4 步骤3:编写Dockerfile与初始化脚本
4.4.1 Dockerfile编写
创建Dockerfile,指令功能如下表所示:
指令 | 具体内容 | 功能说明 |
---|---|---|
FROM | centos:7 |
基础镜像,同前序案例 |
ADD | Centos-7.repo /etc/yum.repos.d/ 、epel-7.repo /etc/yum.repos.d/ |
配置YUM源,确保软件正常安装 |
RUN | yum -y install nginx php-fpm php-gd php-mbstring unzip |
安装核心软件: - nginx:Web服务器 - php-fpm:PHP解析服务 - php-gd:PHP图像处理扩展(可道云预览图片需依赖) - php-mbstring:PHP多字节字符串扩展(可道云处理中文需依赖) - unzip:解压可道云压缩包 |
RUN | sed -i '/^user/c user=nginx' /etc/php-fpm.d/www.conf |
修改PHP-FPM的运行用户为nginx (默认为apache ),避免Nginx与PHP-FPM的文件权限冲突(Nginx默认运行用户为nginx ) |
RUN | sed -i '/^group/c group=nginx' /etc/php-fpm.d/www.conf |
同理,修改PHP-FPM的运行组为nginx |
COPY | nginx.conf /etc/nginx/nginx.conf |
将本地自定义的nginx.conf 复制到容器内的/etc/nginx/ 目录(覆盖默认Nginx配置) |
RUN | mkdir /code |
在容器内创建可道云的应用根目录/code (与Nginx配置中的root /code 对应) |
WORKDIR | /code |
设置工作目录为/code (后续命令均在此目录执行) |
COPY | kodexplorer4.40.zip . |
将本地的可道云压缩包复制到当前工作目录(/code ) |
RUN | unzip kodexplorer4.40.zip |
解压可道云压缩包到/code 目录(生成kodexplorer 子目录,包含应用代码) |
RUN | chown -R nginx.nginx . |
递归修改/code 目录及其子文件的所有者和所属组为nginx ,解决Nginx与PHP-FPM的文件读写权限问题 |
ADD | init.sh /init.sh |
将本地的初始化脚本init.sh 复制到容器内的/ 目录 |
EXPOSE | 80 |
声明容器暴露80端口(Nginx默认端口) |
ENTRYPOINT | ["/bin/bash","/init.sh"] |
容器启动时执行/init.sh 脚本(与CMD类似,但ENTRYPOINT优先级更高,且可接收外部参数) |
完整Dockerfile编写命令:
bash
[root@docker kod]# vim Dockerfile
# 粘贴上述指令,保存退出
FROM centos:7
RUN rm -rf /etc/yum.repos.d/*
ADD Centos-7.repo /etc/yum.repos.d/
ADD epel-7.repo /etc/yum.repos.d/
RUN yum -y install nginx php-fpm php-gd php-mbstring unzip
RUN sed -i '/^user/c user=nginx' /etc/php-fpm.d/www.conf
RUN sed -i '/^group/c group=nginx' /etc/php-fpm.d/www.conf
COPY nginx.conf /etc/nginx/nginx.conf
RUN mkdir /code
WORKDIR /code
COPY kodexplorer4.40.zip .
RUN unzip kodexplorer4.40.zip
RUN chown -R nginx.nginx .
ADD init.sh /init.sh
EXPOSE 80
ENTRYPOINT ["/bin/bash","/init.sh"]
4.4.2 编写初始化脚本init.sh
可道云需同时运行Nginx与PHP-FPM两个服务,且需保持前台进程运行(避免容器退出)。init.sh
脚本功能如下:
- 启动PHP-FPM服务(后台运行,通过
-D
参数); - 接收外部参数并追加到Nginx配置文件(可选,本案例用于测试);
- 启动Nginx服务(前台运行,通过
daemon off;
)。
脚本编写命令与内容:
bash
[root@docker kod]# vim init.sh
# 写入以下内容:
#!/bin/bash
php-fpm -D # 启动PHP-FPM,-D参数表示后台运行(守护进程模式)
echo "$1" >> /etc/nginx/nginx.conf # 将外部参数($1)追加到Nginx配置文件(本案例测试用,无实际功能)
nginx -g 'daemon off;' # 启动Nginx,前台运行(确保容器不退出)
# 赋予脚本执行权限:
[root@docker kod]# chmod +x init.sh
4.5 步骤4:镜像构建与容器运行
4.5.1 构建可道云镜像
在/opt/dockerfile/kod
目录执行构建命令,标签为kod:v3
:
bash
[root@docker kod]# docker build -t kod:v3 .
# 构建过程中会自动执行Dockerfile指令,成功后通过`docker images`可查看`kod:v3`镜像
4.5.2 运行可道云容器
将主机的80端口映射到容器的80端口(若主机80端口未被占用),并传递测试参数#testtest
(通过ENTRYPOINT传递给init.sh
):
bash
[root@docker kod]# docker run -itd --name kod -P kod:v3 '#testtest'
# 输出示例:a9eb681a966288797d5fe096d035ae7d1649b20216d1f844cfd7bb1f0abb81c9(容器ID)
# '#testtest':传递给`init.sh`的参数($1),会追加到Nginx配置文件(测试用)
4.6 步骤5:可道云平台初始化与验证
-
浏览器访问初始化 :
在本地浏览器输入
http://192.168.100.10
(Docker主机IP),进入可道云"运行环境检测"页面,系统自动检测Nginx、PHP、权限等配置,若全部显示"正常",进入下一步。 -
设置管理员密码 :
页面提示"设置管理员密码",输入两次相同的密码(如
admin123
),点击"登录"。 -
平台使用验证 :
登录后进入可道云文件管理界面,可上传、下载、管理文件,说明可道云平台搭建成功。
五、案例总结与核心知识点
5.1 案例共性与差异
维度 | 案例一(Nginx) | 案例二(扫雷游戏) | 案例三(可道云) |
---|---|---|---|
基础镜像 | CentOS 7 | CentOS 7 | CentOS 7 |
核心服务 | Nginx | Tomcat | Nginx + PHP-FPM |
应用类型 | 静态网页 | Java Web(JSP) | PHP Web |
端口暴露 | 80 | 8080 | 80 |
关键指令 | CMD(启动Nginx) | CMD(执行init.sh启动Tomcat) | ENTRYPOINT(执行init.sh启动双服务) |
5.2 核心Dockerfile指令总结
- FROM:指定基础镜像,所有构建的起点,推荐使用官方或可信镜像(如centos:7、ubuntu:20.04)。
- ADD/COPY:复制文件到容器,ADD支持自动解压与HTTP下载,COPY仅用于本地文件复制(推荐优先使用COPY,功能更明确)。
- RUN :执行命令并创建镜像层,用于安装软件、配置环境(复杂命令可通过
&&
拼接,减少镜像层数)。 - WORKDIR :设置工作目录,后续指令(RUN、CMD等)均在此目录执行,避免使用
cd
命令(cd
仅作用于当前RUN指令)。 - EXPOSE :声明暴露端口,仅为文档说明作用,需通过
docker run -p
实现实际端口映射。 - CMD/ENTRYPOINT :容器启动命令,CMD可被
docker run
后的参数覆盖,ENTRYPOINT不可覆盖且可接收参数(需启动多服务时推荐用ENTRYPOINT执行初始化脚本)。
5.3 容器化部署关键注意事项
- 权限问题 :确保容器内服务运行用户(如Nginx的
nginx
、PHP-FPM的nginx
)与应用目录的所有者一致,避免权限拒绝错误(通过chown
命令配置)。 - 前台进程 :Docker容器依赖前台进程保持运行,需禁止服务的守护进程模式(如Nginx的
daemon off;
、Tomcat的前台启动命令)。 - 镜像精简 :尽量减少镜像层数(如合并RUN指令)、清理无用文件(如YUM缓存
yum clean all
),降低镜像体积。 - 环境一致性:通过Dockerfile固化构建流程,确保每次构建的镜像环境一致,避免"本地能跑,线上不能跑"的问题。
通过以上三个案例的实践,可掌握Dockerfile从简单到复杂的应用场景,理解容器化部署的核心逻辑,为后续自定义应用镜像打下基础。