docker nginx -v 挂载配置文件问题

学习docker为的是部署时能更轻松的解决环境问题,docker启动nginx相比学习了docker的朋友们基本上都会使用了,但要修改配置文件或者是部署dist前端项目就会有点麻烦了,如果直接进入容器,你会发现,容器中的环境基本上是一个阉割版的,Linux上的许多命令在容器中是无法使用的,所以这样是十分麻烦的。好在docker有数据卷挂载技术,但是在启动nginx时又会遇到一堆的问题。
情景再现:

docker run -d -p 80:80 -v /home/nginx/conf:/etc/nginx -v /home/nginx/html:/usr/share/nginx/html --name nginx01 nginx

输入上面命令,回车,再使用docker ps 查看会发现容器并没有正在运行:

[root@localhost home]# docker run -d -p 80:80 -v /home/nginx/conf:/etc/nginx -v /home/nginx/html:/usr/share/nginx/html --name nginx01 nginx
d3dd01432c1f0f2deb588deda51503d88048456c62d66a93f40a811a9c68991f
[root@localhost home]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

使用docker ps -a查看发现容器确实有了,但不知道为什么自动停止了。

[root@localhost home]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS                     PORTS     NAMES
d3dd01432c1f   nginx     "/docker-entrypoint.…"   2 minutes ago   Exited (1) 2 minutes ago             nginx01

这时使用docker logs 容器id(或者容器名)查看容器日志信息

[root@localhost home]# docker logs nginx01
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf is not a file or does not exist
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2021/01/14 03:24:08 [emerg] 1#1: open() "/etc/nginx/nginx.conf" failed (2: No such file or directory)
nginx: [emerg] open() "/etc/nginx/nginx.conf" failed (2: No such file or directory)

大概意思好像是/etc/nginx/nginx.conf没有这个文件,这就有点好奇了,理论上运行一个nginx容器是绝对不会没有配置文件的,那就有可能是这个目录指代的不是容器中的目录。

解决方法:

在docker hub官网上查询了一下发现以下有用的信息:
在这里插入图片描述
官网这段话的大概意思就是,要给nginx挂载卷,要先有一个配置文件才能挂载,具体做法就是先以不挂载卷的形式正常启动一个nginx容器,然后从中cp拷贝一份配置文件,删除这个容器,再重新以挂载卷的形式启动一个新容器。

先把之前的nginx01容器给删除,然后启动一个不挂载卷的nginx。
docker run -d -p 80:80 --name nginx-test nginx

[root@localhost home]# docker run -d -p 80:80 --name nginx-test nginx
278ac2479e5a6054cfdfbbd14171556e1a0065ff8b33f788c4f9a4cb72f4af65
[root@localhost home]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                NAMES
278ac2479e5a   nginx     "/docker-entrypoint.…"   2 seconds ago   Up 2 seconds   0.0.0.0:80->80/tcp   nginx-test
[root@localhost home]#

在Linux中使用curl localhost查看是否正常启动服务,也可以在浏览器上输入服务器或虚拟机ip地址查看,不过端口一定要查看是否暴露了。

[root@localhost home]# curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@localhost home]#

这样就说明正常启动服务了,这个时候就把容器内的配置文件拷贝一份到本机上,使用docker cp命令,不熟悉该命令的可以先使用docker cp --help查看


[root@localhost home]# docker cp --help

Usage:  docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
        docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

Copy files/folders between a container and the local filesystem

Use '-' as the source to read a tar archive from stdin
and extract it to a directory destination in a container.
Use '-' as the destination to stream a tar archive of a
container source to stdout.

Options:
  -a, --archive       Archive mode (copy all uid/gid information)
  -L, --follow-link   Always follow symbol link in SRC_PATH
[root@localhost home]#

我们这里拷贝不需要使用可选参数,先查看一下目录情况:

[root@localhost home]# ls
blog_admin  ceshi  mysql  nginx
[root@localhost home]#

nginx目录是第一次以挂载卷形式启动出现的,虽然容器启动就停止,但目录确确实实生成了,其他目录是我的本地目录。使用rm -rf nginx/删除nginx目录:

[root@localhost home]# rm -rf nginx/
[root@localhost home]# ls
blog_admin  ceshi  mysql
[root@localhost home]#

现在开始执行docker的拷贝命令:
docker cp nginx-test:/etc/nginx /home/nginx/conf

[root@localhost home]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                NAMES
278ac2479e5a   nginx     "/docker-entrypoint.…"   7 minutes ago   Up 6 minutes   0.0.0.0:80->80/tcp   nginx-test
[root@localhost home]# docker cp nginx-test:/etc/nginx /home/nginx/conf
invalid output path: directory "/home/nginx" does not exist
[root@localhost home]#

这说明没有/home/nginx这个目录,可以先创建一个目录,mkdir nginx

[root@localhost home]# ls
blog_admin  ceshi  mysql
[root@localhost home]# mkdir nginx
[root@localhost home]# ls
blog_admin  ceshi  mysql  nginx
[root@localhost home]#

然后再执行上面的docker cp命令:

[root@localhost home]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                NAMES
278ac2479e5a   nginx     "/docker-entrypoint.…"   9 minutes ago   Up 9 minutes   0.0.0.0:80->80/tcp   nginx-test
[root@localhost home]# docker cp nginx-test:/etc/nginx /home/nginx/conf
[root@localhost home]# ls
blog_admin  ceshi  mysql  nginx
[root@localhost home]# cd nginx/
[root@localhost nginx]# ls
conf
[root@localhost nginx]# cd conf/
[root@localhost conf]# ls
conf.d  fastcgi_params  koi-utf  koi-win  mime.types  modules  nginx.conf  scgi_params  uwsgi_params  win-utf
[root@localhost conf]#

这样配置文件就正常拷贝过来了,把这个nginx-test的容器停止并删除。

[root@localhost conf]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS         PORTS                NAMES
278ac2479e5a   nginx     "/docker-entrypoint.…"   12 minutes ago   Up 3 seconds   0.0.0.0:80->80/tcp   nginx-test
[root@localhost conf]# docker stop nginx-test
nginx-test
[root@localhost conf]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@localhost conf]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                     PORTS     NAMES
278ac2479e5a   nginx     "/docker-entrypoint.…"   12 minutes ago   Exited (0) 5 seconds ago             nginx-test
[root@localhost conf]# docker rm nginx-test
nginx-test
[root@localhost conf]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@localhost conf]#

然后再使用第一次的挂载卷形式,启动容器。

[root@localhost conf]# docker run -d -p 80:80 -v /home/nginx/conf:/etc/nginx -v /home/nginx/html:/usr/share/nginx/html --name nginx01 nginx
3ccd5825375603510538fd07b8b39bd9cbb0924881c9b7041e87f702aa379424
[root@localhost conf]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                NAMES
3ccd58253756   nginx     "/docker-entrypoint.…"   3 seconds ago   Up 2 seconds   0.0.0.0:80->80/tcp   nginx01
[root@localhost conf]# curl localhost
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.19.6</center>
</body>
</html>
[root@localhost conf]#

看到403的小伙伴别慌,这其实是正常的启动了,但因为/home/nginx/html目录下是空的,所以才会出现403,因为此时/home/nginx/html对应的是容器中的/usr/share/nginx/html目录,可以进到容器中查看目录,如果为空,自然访问80端口服务不会有任何东西了。

[root@localhost conf]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                NAMES
3ccd58253756   nginx     "/docker-entrypoint.…"   3 minutes ago   Up 3 minutes   0.0.0.0:80->80/tcp   nginx01
[root@localhost conf]# docker exec -it nginx01 /bin/bash
root@3ccd58253756:/# cd /usr/share/nginx/html
root@3ccd58253756:/usr/share/nginx/html# ls
root@3ccd58253756:/usr/share/nginx/html#

这个时候只需要在本地主机目录的/home/nginx/html目录下放上一个index.html就行了(使用exit命令退出容器):

[root@localhost html]# pwd
/home/nginx/html
[root@localhost html]# ls
[root@localhost html]# touch index.html
[root@localhost html]# ls
index.html
[root@localhost html]# cat index.html
[root@localhost html]# vi index.html
[root@localhost html]# cat index.html
hello world
[root@localhost html]#

这个时候再去访问80端口:

[root@localhost html]# curl localhost
hello world
[root@localhost html]#

以上就完成了docker对nginx的配置文件的挂载。
如果部署dist前端项目,只需要把dist文件夹里的内容全部拷贝到/home/nginx/html下,此时访问80端口,默认就是你的项目,不需要重启容器。

重点!!!防止再踩坑:

因挂载卷映射出来的nginx配置文件,千万不要配置监听端口,因为配置了也只是对nginx容器里面生效!!

切记,不要在/home/nignx/conf的nginx.conf下进行类似如下的监听端口配置:

server {
        listen       9528;
        server_name  localhost;
        root        /usr/share/nginx/html;
        location / {
            try_files $uri $uri/ @router;
            index  index.html index.htm;
        }
        location @router {
            rewrite ^.*$ /index.html last;
        }
    }

如果你进行了这样的配置,也重启了容器,但你会发现仍然无法通过服务器ip:端口的形式访问,无法达到你想要的结果,因为这样的配置只在容器中生效:

[root@localhost conf]# pwd
/home/nginx/conf
[root@localhost conf]# ls
conf.d  fastcgi_params  koi-utf  koi-win  mime.types  modules  nginx.conf  scgi_params  uwsgi_params  win-utf
[root@localhost conf]# cat nginx.conf
server {
   listen      9528;
   server_name  localhost;
   root        /usr/share/nginx/html;
   location / {
       try_files $uri $uri/ @router;
       index  index.html index.htm;
   }
   location @router {
       rewrite ^.*$ /index.html last;
   }
}
[root@localhost conf]# curl localhost
hello world
[root@localhost conf]# curl localhost:9528
curl: (7) Failed connect to localhost:9528; 拒绝连接
[root@localhost conf]#

ps:在cat nginx.conf命令为了方便看配置文件,我把其他的删除,只显示增加的配置内容。

而进入容器是可以正常访问9528端口的:

[root@localhost conf]# docker exec -it nginx01 /bin/bash
root@3ccd58253756:/# curl localhost
hello world
root@3ccd58253756:/# curl localhost:9528
hello world
root@3ccd58253756:/#

如果你仍然需要使用9528或者其他端口访问你所部署的项目的话,可以在运行挂载卷的nginx容器中映射端口时不映射80,而是你所想的端口,例如:
docker run -d -p 9528(或者是其他你想达到的端口):80 -v /home/nginx/conf:/etc/nginx -v /home/nginx/html:/usr/share/nginx/html --name nginx01 nginx

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值