Docker 安装部署、保存分享、分享社区等(本次有 Nginx 中文乱码实战)
适合课堂 / 自学整理,结构:Docker 基础 → 安装 → 核心概念 → 常用命令 → Dockerfile 镜像构建 → Nginx 中文乱码实战(我们前面实操内容)
一、什么是 Docker
1. 传统虚拟机 和 Docker 容器区别
- 虚拟机:完整虚拟一套硬件 + 独立完整操作系统,体积大、启动慢、资源占用高
- Docker(容器):共享宿主机 Linux 内核,只打包程序、依赖、配置,没有独立内核;体积小、秒级启动、资源消耗极低
一句话:虚拟机是 “装完整电脑”,Docker 是 “打包程序运行环境”
2. Docker 核心作用
一次打包,到处运行 开发、测试、生产环境统一,解决经典问题:“我本地能跑,线上不行”
3. Docker 三大核心组件(必考)
- 镜像(Image):只读静态模板(相当于安装包),包含程序、依赖、配置。镜像不能修改,分层存储。
- 容器(Container):镜像运行出来的实例,有一层可读写临时层;程序实际跑在容器里。删除容器,容器内手动修改的内容默认丢失。
- 仓库(Registry):存放镜像的地方,官方公共仓库:Docker Hub
类比理解:镜像 = 蛋糕配方,容器 = 按照配方烤出来的蛋糕实例
二、Docker 安装部署(CentOS 系统,我们实操环境)
环境:CentOS7 / CentOS Stream
1. 前置:卸载旧版本 docker(可选)
yum remove -y docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

2. 安装 yum 工具包
yum install -y yum-utils

3. 设置 docker yum 源(国内推荐阿里云源,速度快)
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

4. 安装 Docker 引擎(ce = 社区免费版)
yum install -y docker-ce docker-ce-cli containerd.io

5. 启动 Docker & 设置开机自启
# 启动
systemctl start docker
# 开机自动启动
systemctl enable docker

6. 验证是否安装成功
docker --version
docker info
# 运行hello-world测试
docker run hello-world

解释:
Unable to find image 'hello-world:latest' locally
# 本地电脑(宿主机)找不到 hello-world:latest 这个镜像
latest: Pulling from library/hello-world
4f55086f7dd0: Pull complete
# 去 Docker Hub 公共仓库拉取 hello-world 镜像,下载完成
Digest: sha256:5dd0d3e6e255913fc30f90b9f2b1d359cc2cbdb48090cc4b65f1676e203243cc
# 镜像的唯一校验值(哈希值,用来确认镜像没被篡改)
Status: Downloaded newer image for hello-world:latest
# 状态:已经下载好了最新版 hello-world 镜像
Hello from Docker!
This message shows that your installation appears to be working correctly.
# 来自Docker的问候!这条信息代表你的Docker安装正常,可以使用。
✅ 优化配置:国内镜像加速(必配,否则拉镜像很慢)
# 创建daemon.json配置文件
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://mirror.baidubce.com"]
}
EOF
# 重启docker生效
systemctl daemon-reload
systemctl restart docker

三、Docker 基础常用命令(分类整理)
1. 镜像相关
# 搜索镜像
docker search nginx
# 拉取镜像(不加tag默认latest最新版)
docker pull nginx:1.27
# 查看本地镜像
docker images
# 删除镜像(镜像id/名字)
docker rmi 镜像ID

2. 容器相关(高频)
# 创建并启动容器
# -d 后台运行 --name 自定义名字 -p 宿主机端口:容器内端口 镜像名:tag
docker run -d --name nginx-test -p 8080:80 nginx:1.27
# 查看正在运行容器
docker ps
# 查看所有容器(包含停止的)
docker ps -a
# 停止容器
docker stop 容器名/容器ID
# 启动已存在的容器
docker start 容器名/容器ID
# 删除容器(必须先停止,加-f强制删除正在运行的)
docker rm -f 容器名/容器ID
# 进入正在运行的容器内部
docker exec -it 容器名 /bin/bash
# 宿主机 和 容器之间 文件互传
# 宿主机文件 → 容器
docker cp 本地文件 容器名:容器内路径
# 容器文件 → 宿主机
docker cp 容器名:容器内路径 本地路径

做端口映射的时候要用如果是在linux虚拟机上要用内网IP,如果是云服务器的话就用公网IP(云服务器本身自带独立公网 IP,这里的公网 IP,不是 Docker 单独的 IP,是这台服务器整机的公网 IP,Docker 只是把本机 80 端口转发到容器内部),这样就可以在浏览器打开你的docker了。

3. 其他辅助
# 查看容器日志
docker logs 容器名
四、Dockerfile 构建自定义镜像(重点,本次 Nginx 实战核心)
需求:不直接用官方原始 nginx 镜像,自己定制环境、文件,打包成新镜像 ✅ 核心规则:Dockerfile 里每一条指令都会生成镜像分层,镜像只读固化
常用 Dockerfile 指令
表格
| 指令 | 作用 |
|---|---|
| FROM | 基础镜像,必须第一行 |
| ENV | 设置环境变量 |
| COPY | 把宿主机文件复制进镜像内 |
| RUN | 构建镜像时执行命令 |
| EXPOSE | 声明容器要开放的端口(仅声明,不实际开放) |
| CMD | 容器启动默认执行命令 |
nginx:1.27 镜像是 Debian 基础镜像,容器内默认字符集是 POSIX(不是 UTF-8),Shell 不识别中文,直接把中文转成八进制编码 \345\260\232...,最终网页渲染出现乱码 / 繁体异常。

✅ 我们实战最终 Dockerfile(v2 版本,固化 utf8 环境 + 带 meta 的 html)
FROM nginx:1.27
# 系统级UTF8编码,固化在镜像,不会被echo修改
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
# 将本地写好的完整html打包进镜像
COPY index.html /usr/share/nginx/html/index.html
# 声明端口
EXPOSE 80
✅ 构建镜像命令
# -t 镜像名:版本号 . 代表当前目录找Dockerfile
docker build -t mynginx-dockerfile:v2 .

五、文件重定向符号(本次踩坑重点)
表格
| 符号 | 含义 | 风险 |
|---|---|---|
> | 覆盖写入 | 清空原有全部内容,再写入新内容❗ 本次乱码根源 |
>> | 追加写入 | 保留原有内容,新内容加到末尾 ✅ |
# 覆盖(危险,会删掉meta标签)
echo "<h1>测试文字</h1>" > index.html
# 追加(安全)
echo "<p>新增一行</p>" >> index.html
# 多行写入完整html
cat > index.html <<EOF
完整html代码
EOF
六、Nginx 中文乱码实战复盘(我们前面完整踩坑 + 解决,重点)
两个独立 UTF-8 配置(极易混淆)
ENV LANG=C.UTF-8(系统编码) 作用:Linux 底层存储中文不乱码,固化在镜像,echo 修改不了 缺陷:不会通知浏览器编码格式<meta charset="utf-8">(html 内标签) 作用:告诉浏览器使用 utf8 解析页面 本质:只是 html 里一段文本,一旦>覆盖文件直接消失 → 浏览器乱码
现象复现流程
- 基于 v2 镜像启动容器,index.html 自带 meta 标签,中文正常
- 进入容器执行
echo "<h1>测试</h1>" > index.html - index.html 原有全部代码清空,meta 标签消失 → 网页乱码
- 重点:系统编码依旧是 UTF8,文字本身没问题,只是缺少网页编码声明
- 解决方案:想要永久保留完整 html,必须写入 Dockerfile 重新 build 镜像,而不是容器内手动修改
关键结论
容器内直接修改文件 = 临时生效,删除容器就丢失 想要永久固化配置 / 文件 → Dockerfile + docker build 打包镜像
七、拓展方案(可选笔记)
方案 1:安全修改页面(追加内容,不破坏 html 结构)
echo "<p>新增文字</p>" >> /usr/share/nginx/html/index.html
方案 2:生产级 Nginx 全局 utf8(nginx 响应头强制编码,不需要 meta 标签)
FROM nginx:1.27
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
RUN echo 'charset utf-8;' >> /etc/nginx/conf.d/default.conf
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80
八、一句话速记总结(背诵版)
- Docker 共享宿主机内核,轻量、秒启动,核心:镜像、容器、仓库
- Dockerfile 构建镜像,镜像只读固化;容器可读写临时层,容器内修改默认不持久
>覆盖清空文件,>>追加内容ENV C.UTF-8管系统存储文字,meta charset管浏览器解析网页- 永久修改环境 / 文件 → build 镜像;临时调试 → 直接改运行容器
九、保存镜像
1、可以把镜像打包发给别人使用


保存也加载(load)输出别人发给我们的镜像之后,我让他继续运行run运行后,给他设置名字,以及端口映射

然后区去浏览器看下 ,是不是和别人发我们镜像页面一样,一样的就成功啦

十、镜像分享到社区
Docker Hub 就是 Docker 官方公共社区,别人可以直接 docker pull 下载你的镜像Docker
前置准备
- 浏览器打开 https://hub.docker.com 注册账号,记住你的Docker Hub 用户名(全部小写)
- 网页上点
Create repository创建仓库,仓库名小写,选择 Public(公开)
仓库名字建议:
mynginx,和本地镜像对应。


完整 4 步命令实操
①给本地镜像打 tag(最重要!)
格式:docker tag 本地镜像:版本 你的hub用户名/仓库名:版本
示例:假设你的 docker hub 用户名是
atguigudemo
# 本地镜像 mynginx:v1 → 改成符合hub规范名字
docker tag mynginx:v1 atguigudemo/mynginx:v1
⚠️坑:必须带上你的用户名,不能直接写
mynginx:v1push,会报错。

打完 tag 查看:
docker images | grep hub里的用户名
②服务器命令行登录 Docker Hub
docker login
输入你的 DockerHub 用户名;
密码现在推荐用网页生成的Access Token,不要用账号原始密码登录。 登录成功提示:
Login Succeeded
③push 推送上传到社区仓库
docker push 用户名/mynginx:v1
Docker 会分层上传镜像,全部层上传完成,网页 Docker Hub 仓库就能看到你的镜像。

可以在你的镜像这里添加说明书:

显示发布的版本和最新版本

④别人任意机器直接下载使用(分享完成)
其他人不需要 tar 包,一条命令拉取:
docker pull atguigudemo/mynginx:v1
docker run -d -p 8082:80 atguigudemo/mynginx:v1
📝笔记:两套分享方式对比
表格
| 分享方式 | 命令 | 特点 |
|---|---|---|
| 离线分享 | save‑load | 生成 tar 文件,拷贝文件给别人,不能网络 pull |
| 社区公开分享 (Docker Hub) | tag → login → push | 上传公共仓库,全世界可以 pull 下载 |
完整标准工作流(无 commit)
Dockerfile → docker build → docker tag → docker push
高频踩坑
- ❌直接 push
mynginx:v1报错:denied: requested access to the resource is denied
原因:镜像名字缺少你的 hub 用户名命名空间,必须 docker tag 重命名。
- 镜像名全部小写,不能大写字母,Docker Hub 强制要求。
latest标签坑:尽量用明确版本号v1,不要无脑用 latest,版本会混乱。- 国内服务器访问 Docker Hub 网络慢 / 推不上去:需要配置 docker 镜像加速器。
退出登录(可选)
docker logout
两套分享总结
- 内网 / 不能上网环境:用
docker save‑loadtar 包 - 对外分享给所有人:Docker Hub
tag + push
常用命令:

注:如果是云服务器的话,允许哪些端口访问是要在服务器上设置的;
两层防护
第一层:云厂商安全组(阿里云 / 腾讯云… 网页控制台配置)
⚠️这个不在 Linux 命令里面操作!网页后台设置
云服务器外面还有一层防火墙,叫安全组。
就算你 Linux 系统 firewalld 关了,如果安全组没放行端口,外网依旧访问不了。
举例:
你容器 -p 8082:80,宿主机用 8082 端口
👉安全组入方向规则,需要放行 8082 端口,允许来源 0.0.0.0/0(所有 IP)。
如果你用 -p 80:80,就要放行 80 端口。
坑:只改 Linux 内部防火墙,忘记云平台安全组,浏览器访问超时。
第二层:Linux 系统内部防火墙 firewalld(服务器命令行操作)
CentOS7/8 默认开启 firewalld
bash
#查看当前放行端口
firewall-cmd --list-all
两种处理方式(练习环境选其一)
1、临时放行端口(重启服务器失效)
bash
firewall-cmd --add-port=80/tcp
2、直接关闭防火墙(学习测试环境,简单粗暴)
bash
systemctl stop firewalld
systemctl disable firewalld
完整访问判断排查顺序(记笔记,排错顺序)
浏览器访问不通,按顺序排查,从上往下:
✅容器状态:docker ps 容器状态是 Up
✅服务器本机内部测试:curl 127.0.0.1:端口
如果 curl 本机都失败 → Docker 容器 /nginx 服务本身问题
✅Linux 防火墙:firewalld 放行对应端口,或者关闭
✅云服务器安全组:网页控制台放行宿主机映射出来的端口
注意:放行的是宿主机端口,不是容器内部 80 端口。
例如 -p 8082:80,安全组放行 8082,不是 80。
举例子:
docker run -d -p 8082:80 mynginx:v1
容器内部端口:80
宿主机对外端口:8082
安全组、firewalld,都要放行 8082
虚拟机(你现在 CentOS 虚拟机,不是云服务器)
你现在本地 VMware 虚拟机,没有云厂商安全组!只有 firewalld 一层。
只需要处理系统防火墙即可。
区分记忆:
本地虚拟机:只有 Linux firewalld
阿里云 / 腾讯云云服务器:安全组 + firewalld 两层防火墙
高频踩坑
安全组放行容器内部端口,不放宿主机端口 → 访问失败
curl 服务器内部 127.0.0.1 能通,外网浏览器打不开:90% 是安全组没开。
安全组改完有时候十几秒才生效。
简单总结一句话
云服务器对外暴露服务,安全组和系统防火墙都要考虑;虚拟机只需要管系统防火墙。放行的是宿主机映射后的端口。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)