Search code examples
dockerdocker-composedockerfileboot2dockerdocker-machine

Docker apache and nginx port conflict


Description

I have a project with the following configurations:

1) A main website is written in PHP

2) The API is written in NodeJS

Since I develop on several machines running different operating systems, I have decided to use docker so I can run the project on whatever machine I am using.

I am trying to have nginx as a reverse proxy that servers the API and the website in the following manner:

1) example.com --> Website

2) api.example.com --> API

However it seems that Apache is being assign port 80 automatically even if I have not exposed it. This causes a conflict with nginx which also runs on the same box. Is there a way to prevent apache/php from binding automatically to the host's port 80.

I have tried to map the port to a different port but this caused the apache/php to simply add an extra port as you can see here below:

docker ps
CONTAINER ID        IMAGE                COMMAND                  CREATED                     STATUS              PORTS                          NAMES
fc830d3562e4        apache_website   "docker-php-entrypoin"   3 seconds ago       Up 2 seconds        80/tcp, 0.0.0.0:80->8000/tcp       apache_website_run_7

docker-compose file

version: '2' 
services:
  nginx:
    build: nginx
    ports:
     - "80:80"
    expose: 
      - "80" 
    restart: always
    depends_on:
     - website   
     - api
  api:     
    image: node
    command: node /var/www/index.js
    restart: always
  website:
    build: php:7.1-apache        
  ports:
     - "80:800"
  restart: unless-stopped

nginx dockerfile

  FROM nginx
  COPY nginx.conf /etc/nginx/nginx.conf

  EXPOSE 80

nginx config file

worker_processes 4;

events { worker_connections 1024; }

http {
  include mime.types;
  # fallback in case we can't determine a type
  default_type application/octet-stream;

  upstream example.com {
    server website:80 fail_timeout=0;
  }

  server {
    listen 80;
    client_max_body_size 4G;

    keepalive_timeout 5;

    root /opt/app/public;

    location / {
      try_files $uri @proxy_to_app;
    }

    server_name example.com;

    location @proxy_to_app {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

      proxy_set_header Host $http_host;

      proxy_redirect off;
      proxy_pass http://example.com;
    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
      root /opt/app/public;
    }
  }

  # API
  #========================================================================
  upstream api.example.com {
    server api:80 fail_timeout=0;
  }
  server {
    listen 80;
    client_max_body_size 4G;

    keepalive_timeout 5;

    root /opt/app/public;

    location / {
      try_files $uri @proxy_to_app;
    }

    server_name api.example.com;

    location @proxy_to_app {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect off;


      proxy_pass http://api.example.com;
    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
      root /opt/app/public;
    }
  }  
}

How do I prevent Apache/PHP from binding to the host's port 80? I would like to keep the port for the inter-container connections however I don't want the port to be exposed to the host.

I would like to expose port 80 only for nginx.

Please note that I am aware that we can change apache's configurations to make it listen to a different port by changing the ports.config file as I consider this a hack. However I don't want to do this way. I want to make the modification using docker if possible.

I don't undestand why the port is being exposed without me specifying that in docker-compose file.


Solution

  • https://docs.docker.com/compose/compose-file/#/ports explains that the host port comes first. You're explicity exposing port 80 for nginx and for apache. For nginx you're exposing container 80 as host 80, and in apache container 800 as port 80.

    Likely you just got the numbers reversed.