My Wiki!

Hosting Multi Webs with Docker

1. Multi-tenant hosting server

vfoss operation Creating something similar to plesk

2. Quickstart

VFOSS.ORG docker

  cd /srv/vhosts/vfoss.org/vfoss_docker
  sudo   service nginx start
  docker-compose -f ./eco/backend/docker-compose.yml up -d vfoss_db
  docker-compose -f ./eco/backend/docker-compose.yml up -d vfoss_web

2.1 Important folders

Under

  /srv/vhosts
  
[root@v22017014219143544 vhosts]# tree -L 3
.
├── anthenao.com
│   ├── docker
│   │   ├── anthenao_db
│   │   ├── anthenao_web
│   │   ├── data
│   │   └── eco
│   ├── error_docs
│   │   ├── bad_gateway.html
│   │   ├── bad_request.html
│   │   ├── forbidden.html
│   │   ├── internal_server_error.html
│   │   ├── maintenance.html
│   │   ├── method_not_allowed.html
│   │   ├── not_acceptable.html
│   │   ├── not_found.html
│   │   ├── not_implemented.html
│   │   ├── precondition_failed.html
│   │   ├── proxy_authentication_required.html
│   │   ├── request-uri_too_long.html
│   │   ├── unauthorized.html
│   │   └── unsupported_media_type.html
│   ├── httpdocs
│   │   ├── css
│   │   ├── favicon.ico
│   │   ├── img
│   │   ├── index.html
│   │   └── test
│   └── logs
│       ├── access_log
│       ├── access_log.processed
│       ├── access_log.webstat
│       ├── access_ssl_log
│       ├── access_ssl_log.processed
│       ├── access_ssl_log.webstat
│       ├── error_log
│       └── error_log.nginx
├── chroot
├── default
│   ├── cgi-bin
│   ├── htdocs
│   │   ├── css
│   │   ├── favicon.ico
│   │   ├── img
│   │   └── index.html
│   └── httpsdocs
├── fs
│   ├── partner
│   ├── public
│   ├── shared
│   └── unlisted
├── system
│   ├── anthenao.com
│   │   ├── conf
│   │   ├── etc
│   │   ├── logs
│   │   ├── pd
│   │   └── statistics
│   ├── default
│   │   ├── conf
│   │   ├── docker
│   │   ├── etc
│   │   ├── logs
│   │   ├── pd
│   │   └── statistics
│   ├── vfoss.org
│   │   ├── conf
│   │   ├── etc
│   │   ├── logs
│   │   ├── pd
│   │   └── statistics
│   └── vsrc.com
│       ├── conf
│       ├── etc
│       ├── logs
│       ├── pd
│       └── statistics
└── vfoss.org
    ├── docker_data
    │   └── var
    ├── error_docs
    │   ├── bad_gateway.html
    │   ├── bad_request.html
    │   ├── forbidden.html
    │   ├── internal_server_error.html
    │   ├── maintenance.html
    │   ├── method_not_allowed.html
    │   ├── not_acceptable.html
    │   ├── not_found.html
    │   ├── not_implemented.html
    │   ├── precondition_failed.html
    │   ├── proxy_authentication_required.html
    │   ├── request-uri_too_long.html
    │   ├── unauthorized.html
    │   └── unsupported_media_type.html
    ├── httpdocs
    │   ├── css
    │   ├── favicon.ico
    │   ├── img
    │   ├── index.html
    │   └── test
    ├── logs
    │   ├── access_log
    │   ├── access_log.processed
    │   ├── access_log.webstat
    │   ├── access_ssl_log
    │   ├── access_ssl_log.processed
    │   ├── access_ssl_log.webstat
    │   ├── error_log
    │   └── error_log.nginx
    ├── postgres_backups
    │   ├── vfoss_dump_19-02-2017_16_25_28.sql
    │   ├── vfoss_dump_19-02-2017_17_12_57.sql
    │   └── vfoss_dump_19-02-2017_22_40_07.sql
    ├── vfoss_docker
    │   ├── eco
    │   ├── nginx
    │   ├── README.md
    │   ├── run_dev.sh
    │   ├── vfoss_db
    │   └── vfoss_web
    └── vfoss_web_data
        ├── media
        └── static

3. nginx

using system nginx - no docker

  /etc/nginx.conf
  

Including nginx conf of all domains under /srv/vhosts/system:

include /srv/vhosts/system/*/conf/nginx.conf;

Start nginx

  service nginx start
  

4. Start docker images for each domain

  cd /srv/vhosts/vfoss.org/vfoss_docker
  # start detached (background)
  docker-compose -f ./eco/backend/docker-compose.yml up -d vfoss_db
  docker-compose -f ./eco/backend/docker-compose.yml up -d vfoss_web
  

Note: django output some migration errors, but does not affect normal operation

Official NGIX Docker Image

Ngix image has only ngix and no SSH

Run Ngix with mounted configuration files

The NGINX image uses the default NGINX configuration, so the root directory for the container is/usr/share/nginx/html and the configuration files are in /etc/nginx. If the content on the Docker host is in the local directory /var/www and the configuration files are in /var/nginx/conf, we run the command:

  docker run --name mynginx2 -v /var/www:/usr/share/nginx/html:ro \
  -v /var/nginx/conf:/etc/nginx:ro -P -d nginx

Run Ngix image with updated configuration

The NGINX image has the default NGINX configuration files, including default.conf and example_ssl.conf in/etc/nginx/conf.d. Since we want to use the configuration files from the host, we include commands in the followingDockerfile to delete the default files:

FROM nginx
 
RUN rm /etc/nginx/conf.d/default.conf
 
RUN rm /etc/nginx/conf.d/examplessl.conf
 
COPY content /usr/share/nginx/html
 
COPY conf /etc/nginx

We can then create our own NGINX image by running the following command from the directory where the Dockerfileis located:

  # docker build -t mynginximage1.

Note the period (“.”) at the end of the command. This tells Docker that the build context is the current directory. The build context contains the Dockerfile and the directories to be copied. Now we can create a container using the image by running the command:

  <del># docker run --name mynginx3 -P -d mynginximage1</del>
  sudo docker run -name nginx_cont_1 -p 80:80 -i -t nginx_img_1

Configuring Ngix Server

Assuming we want to copy the files as in the example above, while also specifying volumes for the content and configuration files, we use the following Dockerfile:

FROM nginx

 # content/index.html
 COPY content /usr/share/nginx/html

 COPY conf.d /etc/nginx/

 VOLUME /usr/share/nginx/html
 VOLUME /etc/nginx
 VOLUME /var/log/nginx/log

We then create the new NGINX image by running the following command (again note the final period):

  # docker build -t mynginximage2 .

Now we create an NGINX container using the image by running the command:

  # docker run --name mynginx4 -P -d mynginximage2

We then start a helper container with a shell and access the content and configuration directories of the NGINX container we created in the previous example by running the command. Debian is used for ngix so we use the image here:

  # docker run -i -t --volumes-from mynginx4 --name mynginx4files debian /bin/bash
  root@b1cbbad63dd1:/#
  
  apt-get update; apt-get install nano
  export TERM=xterm
  nano

If you exit the shell by running the exit command, the container terminates. If you want to exit while leaving the container running, use Control-p followed by Control-q. The container can be started and stopped with the following commands:

# docker start mynginx4files

and

  # docker stop mynginx4files

Shell access can be regained to a running container with the command:

  # docker attach mynginx4files

Nginx conf

Sample configuration:

  docker ps
  3a161806ddeb        nginx1              "nginx -g 'daemon off"   21 minutes ago      Up 5 minutes        0.0.0.0:80->80/tcp, 443/tcp   mynginx
  8bafdad58b91        coreos/apache       "/usr/sbin/apache2ctl"   2 hours ago         Up 2 hours          0.0.0.0:3000->80/tcp          mad_goldwasser

nginx container listen on port 80, bound with docker host port 80.

Webserver listen on port 80, bound to docker host port 3000. The proxy should pass request from dockerhostip:80 to dockerhostip:3000!!!

How to get dockerhost IP in nginx conf file???

Nginx nginx.conf

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;      <------ this is it
}

Nginx reverse_proxy.conf

upstream vfossorg {
    server 127.0.0.1:3000; <---------- not working, the ip should be docker host ip
}

upstream anthenaocom {
    server 127.0.0.1:3001;
}

server {
        listen 0.0.0.0:80;
        server_name vfoss.org www.vfoss.org;

        location / {
            proxy_pass         http://vfossorg;
            proxy_redirect     off;
            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-Host $server_name;

        }
}

server {
        listen 0.0.0.0:80;
        server_name anthenao.com www.anthenao.com;

        location / {
            proxy_pass         http://anthenaocom;
            proxy_redirect     off;
            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-Host $server_name;

        }
}

docker-compose

Bind Webapp ports

It depends on what the you're proxying to. In the example I gave above, the containers running Apache are bound to the localhost. Nginx then makes the available externally. How are you launching the containers?

This binds them to port 3000 on the localhost:

docker run -d -p 127.0.0.1:3000:80 coreos/apache /usr/sbin/apache2ctl -D FOREGROUND

while this would make them available externally on port 3000:

docker run -d -p 3000:80 coreos/apache /usr/sbin/apache2ctl -D FOREGROUND

Controlling NGINX

Since we do not have access to the command line of the NGINX container directly, we cannot use the nginx command to control NGINX. Fortunately NGINX can be controlled by signals and Docker provides kill command for sending signals to a container. For example, to reload the NGINX configuration run the command:

  docker kill -s HUP <container name>

If you want to restart the NGINX process, restart the container by running the command:

  docker restart <container name>

Navigation