乐趣区

docker下使用nginx转发数据

在上一周收到了老师的 macmini,用起来很快很轻松,在这里谢谢老师。拿到手第一件事就是安环境了,用张喜硕学长推荐的在 mac 下 docker 的桌面端 kitematic 也是很容易就配好了 redis 和 mysql,在以前使用 nginx 转发时使用的都是本地的 nginx,新装的 docker 还有桌面端,于是我想试一试使用 docker 的 nginx,这样就不必每次都修改配置文件而是新起一个容器就行了。

获取镜像

首先是获取 nginx 的官方镜像:

# 命令行
docker pull nginx

在获取镜像后, 输入 docker images 查看获取的镜像, 并启动一个 nginx 的镜像容器:

docker images
docker run -d --name nginx1 -p 80:80 -p 8030:8030 nginx

- d 表示后台运行,–name 表示容器名字,- p 表示开放的端口, 最后为镜像名: 标签。

成功的话使用浏览器输入 localhost 应该能见到 nginx 欢迎页面,之后将我们的 nginx 配置文件复制到容器中, 进入此容器,查看 nginx 的配置文件:

docker exec -it nginx1 /bin/bash
cat /etc/nginx/nginx.conf


可以看到 nginx 默认是包含 /etc/nginx/conf.d/ 目录下所有.conf 的配置文件了,所以只需要将我们的配置文件复制容器的这个路径上就可以了:

docker cp /xxx/xxx.conf nginx1:/etc/nginx/conf.d/

重新启动容器或者在容器中重新启动 nginx 就可以使 nginx 加载我们的配置了。

保存更改

我们这些在容器里的操作只会保存在当前容器中,当我们删除这个容器后,我们的操作也就都丢失了。docker 镜像设计为分层存储的架构,我们只需要在 nginx 镜像的基础上,保存我们这一层的操作,创建一个新的镜像就可以了。

#docker commit [选项] < 容器名或 id> [< 仓库民 >:< 标签 >]
docker commit nginx1 nginx1:1

使用 docker images 就可以看到新创建的镜像,以后直接启动这个镜像的容器就行了。

访问宿主服务

由于项目的前后台都是这本机上运行的,nginx 容器只是负责转发,但我在启动前后台后,一直无法通过 nginx 访问到,之前的配置文件是这样的:

server {
    # 平台端口
    listen       8030;
    server_name  127.0.0.1 localhost;
    location / {
        proxy_pass http://127.0.0.1:4200/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /api/ {
        # 如有需要,请修改端口值
        proxy_pass http://127.0.0.1:8081/;
        proxy_set_header X-Requested-With XMLHttpRequest;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

在经过查询后,我才了解到了,容器的 ip 和宿主的 ip 地址是不一样的,我这么转发其实转发的是容器里边 4200 端口和 8081 端口的服务,然而容器里并没有启动这两个服务,所以访问是报错的。在 mac 中解决方法是将代理的地址 127.0.0.1 改为 docker.for.mac.host.internal(参考文章), 这样就 nginx 就访问正确的服务了。

后续

经历了这么多麻烦事,勉强是能用了,但随之而来有出现了新问题,当使用 nginx 容器转发静态文件时,挂载本机目录到 nginx 容器上或复制文件到容器内部都可以,但是我感觉这越来越麻烦了,还不如使用本机的 nginx,我在想是不是不因该用 nginx 容器来作为开发,而是用来构建运行环境会更好一些?想象下我们只需要定制一个 dockerfile, 在构建镜像是把打包好的程序拷贝到镜像中,只需要一个 docker run 命令就在任何环境中启动我们的应用,这是不是会更好?

退出移动版