Adrian C.
Adrian C.

Reputation: 270

How to setup dynamic subdomains in docker with NGINX

Basically, I need to have dynamic subdomains, so the site should be available at any subdomain in Docker like this:

admin.example.com adrian.example.com files.example.com .

I don't have a fixed number of subdomains, so I can't just put them all in the hosts file.

Server_name also didn't help: server_name www.$hostname;

They should all point to the same website. I've tried jwilder reverse proxy, but wasn't able to set it up correctly.

I have a docker-compose.yml and Dockerfile.

Could someone give me a working code that I could use, and then change it for my needs. And if I need to change my hosts file also.

I did some research, but my nginx and docker knowledge is not enough.

Nginx.conf

server {
    server_name .example.local;

    listen 80 default;
    client_max_body_size 1008M;
    access_log /var/log/nginx/application.access.log;
    error_log  /var/log/nginx/error.log;
    root /application/web;
    index index.php;

    if (!-e $request_filename) {
        rewrite ^.*$ /index.php last;
    }

    location ~ \.php$ {
        fastcgi_pass php-fpm:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
        include fastcgi_params;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        proxy_buffer_size   128k;
        proxy_buffers   4 256k;
        proxy_busy_buffers_size   256k;
    }

}

Dockerfile

FROM phpdockerio/php73-fpm:latest

RUN mkdir /application
WORKDIR "/application"
COPY . /application

# Fix debconf warnings upon build
ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update                                                                                                  && \
    # Installing packages
    apt-get -y --no-install-recommends --assume-yes --quiet install                                                    \
    nano curl git ca-certificates ruby-dev gcc automake libtool rubygems build-essential make php-pear                 \
    php7.3-mysql php7.3-bcmath php-imagick php7.3-intl php7.3-gd php-yaml php7.3-soap php7.3-dev mysql-client       && \
    # Xdebug
    pecl install xdebug                                                                                             && \
    # Cleaning up after installation
    apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

docker-compose.yml

version: "3.1"
services:

  db:
    image: mysql:5.6
    container_name: ls-db
    working_dir: /application
    volumes:
      - .:/application:cached      # User-guided caching
      - ./phpdocker/sql:/docker-entrypoint-initdb.d
    environment:
      MYSQL_DATABASE: ls
      MYSQL_USER: drupal
      MYSQL_PASSWORD: drupal
      MYSQL_ROOT_PASSWORD: root
    ports:
      - "6006:3306"
    networks:
      - ls

  web:
    image: nginx:alpine
    container_name: ls-webserver
    working_dir: /application
    volumes:
      - .:/application:cached      # User-guided caching
      - ./phpdocker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
    ports:
      - "6060:80"
    networks:
      - ls

  php-fpm:
    build: phpdocker/php-fpm
    container_name: ls-php-fpm
    working_dir: /application
    volumes:
      - .:/application:cached      # User-guided caching
      - ./phpdocker/php-fpm/php-ini-overrides.ini:/etc/php/7.3/fpm/conf.d/99-overrides.ini
    networks:
      - ls

networks:
  ls: # this network (app1)
    driver: bridge

volumes:
  db:

Upvotes: 4

Views: 5316

Answers (1)

DannyB
DannyB

Reputation: 14776

Not sure what have you tried and failed with jwilder's reverse proxy, but it is an excellent way to address the exact issue at hand without dealing with nginx configuration and complex compose configuration.

Here is a working code, and you even do not have to change your host file

version: '3.7'

services:
  nginx:
    image: jwilder/nginx-proxy
    ports: ["80:80"]
    volumes:
    - /var/run/docker.sock:/tmp/docker.sock:ro
    environment:
      DEFAULT_HOST: fallback.lvh.me

  api:
    image: dannyben/whoami
    environment:
      MESSAGE: I am the API
      VIRTUAL_HOST: "*.lvh.me"

  web:
    image: dannyben/whoami
    environment:
      MESSAGE: I am the WEB
      VIRTUAL_HOST: "www.lvh.me"

In order to make it work, you must first launch the nginx proxy:

$ docker-compose up -d nginx

and only then, the backend services

$ docker-compose up -d api web

Then you can access www.lvh.me to see the web backend, and anything-else.lvh.me to see the API backend.

In addition, you can provide multiple wildcard hosts to the VIRTUAL_HOST environment variable, so that it supports both your local development environment and your production environment, like so:

VIRTUAL_HOST: "*.lvh.me,*.your-real-domain.com"

It is important to note that in order for this to work in a production environment, your DNS should also be set to use a wildcard subdomain.

In this demo, lvh.me is just forwarding all traffic to 127.0.0.1, which in turn gets to your nginx, which then forwards traffic inwards to your actual application.

Upvotes: 3

Related Questions