目标
通过实践+理论的方式去理解nginx容器,并且在学习中进行延展性的思考,以深入了解nginx和容器
辅助学习工具:deepseek,chatgpt
前提:docker所在机器需要能访问docker hub,不然无法快速拉取镜像
过程
nginx容器主要目录
# 配置文件目录
/etc/nginx/
├── nginx.conf
├── conf.d/
│ └── default.conf
├── mime.types
# 默认网页根目录
/usr/share/nginx/html/
└── index.html
# 日志目录
/var/log/nginx/
├── access.log
└── error.log
# 可执行文件目录
/usr/sbin/nginx
# 模块目录
/usr/lib/nginx/modules/
└── ngx_http_geoip_module.so
# 缓存目录
/var/cache/nginx/
nginx容器运行
docker search nginx # 查看nginx可用版本
docker pull nginx:latest # 拉取最新nginx镜像
docker images # 查看docker的镜像仓库
docker run -it --rm nginx /bin/bash # 启动nginx临时容器,会启动伪tty进入nginx容器内部,退出后nginx会销毁
docker run --rm nginx cat /etc/nginx/nginx.conf > /usr/local/software/nginx/nginx1/conf/nginx.conf # 拷贝nginx容器内的nginx.conf配置文件到宿主机上
运行nginx,并挂载
docker run -d \
--name nginx1 \
-v /usr/local/software/nginx/nginx1/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /usr/local/software/nginx/nginx1/logs:/var/log/nginx \
-v /usr/local/software/nginx/nginx1/html:/usr/share/nginx/html \
-p 8080:80 \
nginx
# 命令说明
-d 以后台(detached)模式运行容器。
--name nginx1 为容器指定一个名称 nginx1
-v 主机路径:容器路径 将主机的文件/目录挂载到容器内的文件/目录上,是为了让Nginx使用主机上的文件目录,而不是容器内的
-p 8080:80 将容器内的 80 端口映射到主机的 8080 端口,为了通过主机的 30030 端口访问 Nginx 服务
docker exec -it nginx1 nginx -t # 测试nginx容器是否正常运行
docker exec -it nginx nginx -s reload # 使nginx容器重新加载配置
镜像实践
基于nginx镜像创建镜像
# 1 创建文件夹
mkdir webimage
cd webimage/
# 2 创建index.html文件
touch index.html
vim index.html
# 3 编写index.html文件内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>首页</title>
</head>
<body>这是我的nginx镜像 服务器首页</body>
</html>
# 生成Docker
touch Dockerfile
vim Dockerfile
# 编写Dockerfile内容
FROM nginx:latest
COPY index.html /usr/share/nginx/html
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
# 配置Docker Hub中的DockerID到环境变量
export DOCKERID=jaxdeng
echo $DOCKERID # 查看是否配置生效
# 构建Docker镜像
docker image build --tag $DOCKERID/webimage:1.0 . # 注意:命令不要少了 . 指以当前目录作为构建上下文
查看构建的镜像
使用构建的镜像创建容器
# 运行容器
docker run -d -p 30032:80 --name mywebimage $DOCKERID/webimage:1.0
# 删除mywebimage容器
docker rm -f mywebimage
# 构建Docker镜像
docker image build --tag $DOCKERID/webimage:2.0 .
# 查看镜像,过滤查看,如下图可看出由于镜像内容没有做任何更改,1.0和2.0的image id完全一样
docker image ls -f reference="$DOCKERID/*"
上传镜像
# 登录Docker Hub ,Docker所在机器需要能连接Docker hub
docker login
docker image push $DOCKERID/webimage:1.0
扩展思考
镜像中nginx -g "daemon off;"命令的作用
nginx -g "daemon off;"
命令是 启动 Nginx 并使其在前台运行
在nginx镜像中使用这条命令的原因:
容器需要有一个前台进程来保持运行,如果主进程退出,容器会自动停止。Nginx 默认以守护进程(后台)模式运行,这会导致容器启动后立即退出。通过
daemon off;
让 Nginx 在前台运行,确保容器持续运行。容器通常将标准输出和错误输出捕获为日志,守护进程模式的日志可能无法正确重定向。前台运行的 Nginx 将日志直接输出到控制台,方便容器日志管理工具(如 Docker、Kubernete)收集和查看。
容器需要向主进程发送信号(如
SIGTERM
)来管理其生命周期,守护进程模式可能导致信号无法正确传递。前台运行的 Nginx 可以直接接收和处理这些信号,确保容器能正常停止或重启。容器设计为单进程模型,前台运行的 Nginx 符合这一设计,简化了容器的进程管理。
卷挂载和绑定挂载区别
卷挂载(Volume Mount)
定义:使用 Docker 管理的存储卷(Volume),卷由 Docker 创建和管理,存储在主机上的特定目录(通常为
/var/lib/docker/volumes/
)。特点:
持久化:数据独立于容器生命周期,容器删除后数据仍保留。
易于备份和迁移:Docker 提供命令(如
docker volume create
、docker volume inspect
)管理卷。性能:通常比绑定挂载性能更好,适合高读写场景。
路径管理:路径由 Docker 自动管理,无需指定主机路径。
挂载后对容器内文件的影响:
如果挂载目标路径(容器内路径)原本有文件,挂载后会被卷中的内容覆盖。
如果卷为空,容器内路径的文件会复制到卷中。
docker run -v my-volume:/app/data my-image
绑定挂载(Bind Mount)
定义:将主机上的特定文件或目录直接挂载到容器中,需要明确指定主机路径和容器路径。
特点:
灵活性:可以挂载任意主机文件或目录。
依赖主机路径:需要确保主机路径存在,路径错误会导致挂载失败。
性能:性能略低于卷挂载,适合开发调试或配置文件挂载。
数据管理:数据存储在主机指定路径,需手动管理备份和迁移。
挂载后对容器内文件的影响:
如果挂载目标路径(容器内路径)原本有文件,挂载后会被主机路径的内容覆盖。
如果主机路径为空,容器内路径的文件会被清空。
docker run -v /host/path:/app/data my-image
问题记录
配置挂载问题
分析:从 docker logs
的输出nginx: [emerg] open() "/etc/nginx/nginx.conf" failed (2: No such file or directory)
可以看出,Nginx 容器启动失败的原因是:无法找到 /etc/nginx/nginx.conf
文件。这是因为在运行容器时挂载了一个宿主机的目录到 /etc/nginx
,但该目录中缺少 nginx.conf
文件,或者路径配置有误。
定位原因:是宿主机下/usr/local/software/nginx/nginx1/conf
目录为空,挂载到容器后,容器内的 /etc/nginx
目录也会是空的,导致 Nginx 无法找到配置文件而报错
原理:容器的绑定挂载机制的特性:
当挂载一个宿主机的目录到容器内时,容器内的目标目录会被完全替换为宿主机目录的内容。
如果宿主机目录是空的,容器内的目标目录也会变成空的。
评论区