/ Docker

记一次用 Docker 运行 Nginx 容器做域名反向代理时踩的坑

最近重新建博客,正好在熟悉 Docker,就用 Docker 创建了一个 Ghost 容器,由于 Ghost 被我映射到宿主机的 8080 端口,于是决定用 Docker 再创建个 Nginx 容器来做域名反向代理,结果开始了踩坑之路…… 눈_눈

整个过程是这样:

1. 创建 Nginx 和 Ghost 容器

Nginx 对应宿主机 80 端口,将 conf.d 文件夹挂载到宿主机:

docker run -p 80:80 --name nginx_80 -v /root/nginx_80/conf.d:/etc/nginx/conf.d -d nginx

注:如果有需要,可以把 Nginx 的以下文件夹都挂载到宿主机:

  • /etc/nginx/conf.d
  • /etc/nginx/nginx.conf
  • /var/log/nginx
  • /usr/share/nginx/html

对应命令:

docker run -p 80:80 --name nginx_80 -v /root/nginx_80/conf.d:/etc/nginx/conf.d -v /root/nginx_80/nginx.conf:/etc/nginx/nginx.conf:ro -v /root/nginx_80/html:/usr/share/nginx/html -v /root/log/nginx:/var/log/nginx -d nginx

先说这里的一个小坑:挂载 conf.d 后,由于文件夹中可能会因为没有 default.conf 文件而导致访问直接宿主机 IP 无法看见「Welcome to nginx!」的页面,以至于以为 Nginx 没运行成功。所以要么通过查询 Nginx 运行状态确认,或者从官网拷贝一份 default.conf 过来。

接下来是创建 Ghost 容器,对应宿主机 8080 端口,将 content 文件夹和 config.production.json 配置文件挂载到宿主机:

docker run -d -p 8080:2368 --name myghost -v /root/myghost:/var/lib/ghost/content -v /root/myghost/config.production.json:/var/lib/ghost/config.production.json ghost

访问宿主机 IP:8080 能打开 Ghost 博客就算正常了。

2. 配置 Nginx 反向代理

进入第一步中宿主机用来挂载 Nginx 的文件夹 conf.d,用 vi www.abc.com.conf 命令创建域名配置文件并输入以下内容:

server {
    listen  80;
    server_name  www.if404.com;
    access_log /var/log/nginx/if404.access.log main;
    error_log /var/log/nginx/if404.error.log error;
    location / {
        proxy_set_header  Host  $http_host;
        proxy_set_header  X-Real-IP  $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass  http://宿主机IP:8080;
    }
}

保存退出后重启 Nginx 容器:

docker restart nginx_80

然后在浏览器访问域名,结果遇坑:502 错误。

在查了半天资料,做了各种尝试依然无法解决的情况下,在不愿意透露身份的 CMGS 童鞋提醒下,进入 Nginx 容器运行 curl 宿主机IP:8080 无法获取信息后,确定是防火墙的问题……

3.防火墙开启 80、8080 端口

之前其实也想过会不会是防火墙的问题,结果发现系统没安装 iptables 就排除了。直到这一刻才意识到,CentOS7 默认安装的防火墙是 Firewalld 而不是 iptables……

先查询一下已开放端口:

firewall-cmd --list-ports

果然啥都没有,赶紧开放一下:

firewall-cmd --zone=public --add-port=8080/tcp --permanent

运行后提示 success 就意味着添加成功,然后重新加载 Firewalld:

firewall-cmd --reload

再访问域名,总算正常了。