docker + nginx + node.js + php-fpm

2019-06-08 11:50发布

问题:

everyone.

I have some problems with launching Docker containers. The final task is:

  • nginx with 80 and 443 ports as a reverse proxy to localhost:3000 (it's ok);
  • node.js with 3000 port is frontend (it's ok);
  • php-fpm with 9000 port and domain.con/api url (it's not working);

So, the main problem is with nginx.conf:

upstream app {
    server app:3000;
}

server {
    listen 80;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    location / {
        try_files $uri @app;
    }

    location /api {
        try_files $uri /index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass api:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

    location @app {
        proxy_pass http://app;
    }
}

When I try to get to localhost — it's ok, node.js is working fine; But when I try to get to localhost/api — it gives me an error that file not found.

docker-compose looks like:

version: '3'
services:
    api:
        container_name: api
        build:
            context: ./api
            dockerfile: Dockerfile
        restart: unless-stopped
        volumes:
            - ./api:/var/www
            - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
        ports:
            - '9000:9000'
        networks:
            - app-network
    app:
        container_name: app
        build:
            context: ./app
            dockerfile: Dockerfile
        restart: always
        ports:
            - '3000'
        volumes:
            - ./app:/app
        networks:
            - app-network
    nginx:
        container_name: nginx
        image: nginx:alpine
        restart: unless-stopped
        volumes:
            - ./api:/var/www
            - ./nginx/:/etc/nginx/conf.d
        ports:
            - '80:80'
        depends_on:
            - app
            - api
        networks:
            - app-network
networks:
    app-network:
        driver: bridge

回答1:

I've been setting up reverse proxies with apache and nginx on numerous occasions and I always found this activity time consuming (not easy to test and debug).

Since I started to work with docker and docker-compose, I found a much easier way to setup a reverse proxy service and now can spend my time on the apps. This easy way is to make use of a Traefik service in your docker compose file:

version: "3"
services:

  reverseproxy:  # see https://docs.traefik.io/#the-traefik-quickstart-using-docker
    image: traefik
    command: --docker
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  backend:
    image: someapp
    expose: 
      - 8080
    labels:
      traefik.frontend.rule: PathPrefixStrip:/api
      traefik.port: 8080

  frontend:
    image: nginx
    volumes: 
      - ./www:/usr/share/nginx/html/:ro
    expose:
      - 80
    labels:
      traefik.frontend.rule: PathPrefixStrip:/
      traefik.port: 80

As you can see, all reverse proxy rules are specified as labels on target containers. Traefik does the reverse proxy job quite well, handling correctly HTTP/2, websockets, forwarding headers, ... It's quite a time saver.