V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
css3
V2EX  ›  程序员

用 docker-compose 启动 nginx, network 为 host, nginx 无法启动是怎么回事?

  •  
  •   css3 · 2020-08-19 16:19:55 +08:00 · 5446 次点击
    这是一个创建于 1563 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大佬们请教个问题:

    场景:docker for mac, 通过 docker-compose 创建 nginx 容器,

    遇到问题( nginx 无法正常运行):

    • 若 docker 的 network 为 host 时,容器启动显示正常,但通过 docker ps -a 不显示 PORTS ,应该是假启动,mac 浏览器访问 lcoalhost 时,直接显示无法访问此网站(我理解的根本就没有启动成功,所以打不开页面)
    • 若 docker 的 network 为默认的,容器启动显示正常,通过 docker ps -a 也能显示映射的 PORTS, 应该是启动成功,mac 浏览器访问 lcoalhost 时,显示的是 nginx 的错误页面(为啥会这样)
    # docker-compse.yml
    version: '3'
    services:
      nginx:
        container_name: nginx
        image: nginx:latest
        ports:
        - 80:80
        network_mode: host
        volumes:
        - /opt/nginx/nginx.conf:/etc/nginx/nginx.conf #宿主机文件已创建
        - /opt/nginx/conf.d:/etc/nginx/conf.d #宿主机目录已创建
        - /opt/nginx/log:/var/log/nginx #宿主机目录已创建
        restart: always
    
    $ docker-compose up -d
    Creating nginx ... done
    
    docker ps -a # PORTS 是空的
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
    cf103d8c33c6        nginx:latest        "/docker-entrypoint.…"   3 seconds ago       Up 2 seconds                            nginx
    
    
    $ docker logs -f nginx  # 为啥提示 read-only file system?
    /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: error: can not modify /etc/nginx/conf.d/default.conf (read-only file system?)
    /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
    /docker-entrypoint.sh: Configuration complete; ready for start up
    
    第 1 条附言  ·  2020-08-19 21:06:08 +08:00

    我其实就是想用nginx 容器解决本地开发中前后端跨域的问题,现在的问题是,启动的nginx容器,识别不了本地localhost 或 127.0.0.1的服务,(至少我还没有找到解决办法)所以也无法代理。

    看到官网推荐用http://host.docker.internal替换localhost或127.0.0.1,但我测试了没能正常访问

    另外就是7楼的老哥说的mac的docker不支持host网络,那这可咋弄呢,真要装个二进制的nginx了么? 我所有的配置及启动信息如下:

    # nginx容器内/etc/nginx/conf.d/default.conf配置如下
    server {
        listen       80;
        server_name  host.docker.internal, localhost, 127.0.0.1;
    
        #charset koi8-r;
        #access_log  /var/log/nginx/host.access.log  main;
    
        keepalive_timeout   70;
    
        gzip on;
        gzip_min_length 200;
        gzip_buffers 4 16k;
        gzip_comp_level 6;
        gzip_types text/plain application/javascript text/css application/xml text/javascript application/json;
        gzip_vary on;
        gzip_disable "MSIE [1-6]\.";
        gzip_proxied any;
    
        # 配置django ,如果符合 /api/ 开头的url,就转发到http://127.0.0.1:8000
        location /api/ {
           proxy_pass http://127.0.0.1:8000;
           proxy_pass_request_headers      on;
           proxy_set_header Host $host;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         }
    
        # 配置vue,默认的所有的请求,都转发到  http://127.0.0.1:8080;  比上面多了几个配置,因为要支持websocket
        location / {
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_pass http://127.0.0.1:8080;
            proxy_pass_request_headers      on;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         }
    
    
    

    然后用docker-compose启动

    # docker-compose up -d
    version: '3'
    services:
      nginx:
        container_name: nginx
        image: nginx:latest
        #ports:
        #- 80:80
        network_mode: host
        volumes:
        - /opt/nginx/nginx.conf:/etc/nginx/nginx.conf
        - /opt/nginx/conf.d:/etc/nginx/conf.d
        - /opt/nginx/log:/var/log/nginx
        restart: always
    

    浏览器访问:

    http://localhost/ # 无法访问此网站
    http://lhost.docker.internal #也打不开
    

    有老哥清楚的吗,搞了一下午了,心态崩了

    19 条回复    2020-08-20 11:19:51 +08:00
    StarUDream
        1
    StarUDream  
       2020-08-19 16:32:14 +08:00
    指定为 "host" 时,所有容器端口都对应属主机端口,在 PORTS 中看不到映射关系。
    hackshen
        2
    hackshen  
       2020-08-19 17:17:51 +08:00
    看看这个 https://docs.docker.com/network/host/
    The host networking driver only works on Linux hosts, and is not supported on Docker Desktop for Mac, Docker Desktop for Windows, or Docker EE for Windows Server.
    anubu
        3
    anubu  
       2020-08-19 17:28:14 +08:00
    ports 部分配置了“80:80”,网络模式没必要了,建议取消配置。应该也不是网络模式导致的异常,建议从权限问题入手排查:
    1. 端口号低于 1024 可能需要特殊权限,确认权限是否足够,可以试试高位端口映射,如“2080:80”
    2. 看报错日志,首先考虑排查挂载的文件权限。如果是手动在外部创建了目录和文件,挂载后可能会有文件权限问题
    aaa5838769
        4
    aaa5838769  
       2020-08-19 17:33:05 +08:00
    你本机有没有 80 端口开放?不包括 nginx
    Reficul
        5
    Reficul  
       2020-08-19 18:51:40 +08:00
    ```
    10-listen-on-ipv6-by-default.sh: error: can not modify /etc/nginx/conf.d/default.conf (read-only file system?)
    ```

    你这个配置又是 Volume 挂进去的,权限问题基本上是。
    Xusually
        6
    Xusually  
       2020-08-19 19:13:07 +08:00
    can not modify /etc/nginx/conf.d/default.conf (read-only file system?)
    wfd0807
        7
    wfd0807  
       2020-08-19 19:36:53 +08:00
    docker for mac 运行容器的宿主实际上是 qemu 虚拟机,所以 host 模式在 mac 上不支持
    css3
        8
    css3  
    OP
       2020-08-19 20:54:14 +08:00 via iPhone
    @StarUDream 哦哦,就是说 network 是 host 时,端口不用映射了,容器外访问任何端口都会指向容器内对应的端口,是这个意思吧?但我看楼下有人说 mac 的 dodocker 不支持 hohost 网络模式😂
    css3
        9
    css3  
    OP
       2020-08-19 21:06:49 +08:00
    @css3 @StarUDream @hackshen @anubu @aaa5838769 @Reficul @Xusually @wfd0807
    老哥们再看看,我说 append 原始需求和最新遇到的问题了
    wfd0807
        10
    wfd0807  
       2020-08-19 21:30:42 +08:00
    @css3 host.docker.internal 是从容器内访问 qemu 虚拟机的宿主机用的

    proxy_pass http://127.0.0.1:8080; ==> proxy_pass http://host.docker.internal:8080;
    css3
        11
    css3  
    OP
       2020-08-19 21:44:53 +08:00 via iPhone
    @wfd0807 我的需求是:本地请求=>nginx 容器转发=>返回本地,如何实现呢
    no1xsyzy
        12
    no1xsyzy  
       2020-08-20 09:36:01 +08:00
    @css3 #9 俺寻思你看看 #2 和 #7 吧
    network_mode: host 不可用
    no1xsyzy
        13
    no1xsyzy  
       2020-08-20 09:37:40 +08:00
    docker 还是 ports: ["80:80"]
    nginx 的代理上游不应该是 127.0.0.1 而应该是 host.docker.internal
    anubu
        14
    anubu  
       2020-08-20 09:56:45 +08:00
    看上去是要利用容器中的 nginx 代理本地宿主机上的一个程序,目前的 proxy_pass 配置肯定是错误的。没用过 Mac 版,按照 Windows 版推测,当前环境至少有三层网络,宿主机》虚拟机》容器,三层分别有各自的 localhost,当前配置挂载到容器中的 nginx 就是反代容器的 localhost:8080,应该是不符合预期的,实际需求应该是希望反代宿主机的 localhost:8080 。

    如果宿主机程序监听 0.0.0.0:8080,可简单修改 prox_pass 为宿主机 IP:8080,应该能达到预期。
    hackshen
        15
    hackshen  
       2020-08-20 11:06:37 +08:00
    同意 14 楼 nginx 里面配置 proxy_pass http://宿主机 IP:端口号;
    如果你电脑 IP 每天更换可以尝试在宿主机修改 host 绑定 ,比如 xxx.xxx.xxx.xx test.baidu.com, nginx 里面配置 proxy_pass http://test.baidu.com;
    css3
        16
    css3  
    OP
       2020-08-20 11:11:51 +08:00
    @css3 @StarUDream @hackshen @anubu @aaa5838769 @Reficul @Xusually @wfd0807 @no1xsyzy

    老哥们,解决了,就是 nginx 容器内配置本地的 ip 要写成像 13 楼老哥的那种,多谢各位了!
    css3
        17
    css3  
    OP
       2020-08-20 11:12:37 +08:00
    @wfd0807 对的,这样解决了问题,多谢老哥指点
    lyhapple
        18
    lyhapple  
       2020-08-20 11:18:03 +08:00
    docker-compose.yml 里加入:
    lyhapple
        19
    lyhapple  
       2020-08-20 11:19:51 +08:00
    networks:
    backend:
    name: backend_network
    driver: bridge

    然后容器里指定:
    nginx:
    // 其它配置
    networks:
    - backend
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2857 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 12:34 · PVG 20:34 · LAX 04:34 · JFK 07:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.