Docker - Run Apache on host and container for different websites Docker - Run Apache on host and container for different websites apache apache

Docker - Run Apache on host and container for different websites


Thanks to VonC's answer I managed to get it working but I slightly changed my architecture, resulting in 3 containers instead of only 1.

I have one container for each Apache / PHP version, and one container with Nginx as reverse proxy. I think you can easily adapt this to install Nginx on the host and change it's configuration to match the architecture I described in my question.

Note that as I'm new to Docker, and a noob regarding Linux system administration, there's probably some mistakes and things that don't make any sense in the following scripts, but it's working for me. Feel free to improve it :)


Nginx Reverse Proxy image

The Dockerfile :

FROM debian:jessieMAINTAINER AntoineB version: 0.1RUN apt-get update && \    apt-get install -y --force-yes \            nginx \        nanoEXPOSE 80EXPOSE 443ADD ./proxy.conf /etc/nginx/conf.d/proxy.confCMD ["nginx"]

Here's the referenced proxy.conf file :

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;client_max_body_size    10m;client_body_buffer_size 128k;client_header_buffer_size 64k;proxy_connect_timeout   90;proxy_send_timeout      90;proxy_read_timeout      90;proxy_buffer_size   16k;proxy_buffers       32   16k;proxy_busy_buffers_size 64k;

And I run it using the following bash script :

docker run -ti -d -p 80:80 -v /home/antoineb/Docker/images/nginxproxy/virtualhosts:/etc/nginx/sites-enabled --name nginxproxy nginxproxy /bin/bash

I have a /home/antoineb/Docker/images/nginxproxy/virtualhosts folder on my host that contains the following default file :

server {       listen 80;       server_name  siteZ.com;       location / {            proxy_pass http://apache22php53:80;       }}server {       listen 80;       server_name  siteA.com;       location / {            proxy_pass http://apache24php56:80;       }}server {       listen 80;       server_name  siteB.com;       location / {            proxy_pass http://apache24php56:80;       }}

Apache 2.2 + PHP 5.3 image

Dockerfile :

FROM debian:wheezyMAINTAINER AntoineB version: 0.1RUN apt-get updateRUN echo "deb http://packages.dotdeb.org squeeze all" > /etc/apt/sources.list.d/dotdeb_squeeze.listRUN echo "deb-src http://packages.dotdeb.org squeeze all" >> /etc/apt/sources.list.d/dotdeb_squeeze.listRUN echo "deb http://ftp.debian.org/debian/ squeeze main contrib non-free" >> /etc/apt/sources.list.d/dotdeb_squeeze.listRUN echo "Package: *php*" > /etc/apt/preferences.d/php53.prefRUN echo "Pin: release o=packages.dotdeb.org,n=squeeze" >> /etc/apt/preferences.d/php53.prefRUN echo "Pin-Priority: 989" >> /etc/apt/preferences.d/php53.prefRUN apt-get update && \    apt-get install -y --force-yes \            apache2 \        php5 \        php5-curl \        php5-gd \        php5-mysql \        nanoRUN a2enmod \            php5 \        rewriteENV APACHE_RUN_USER www-dataENV APACHE_RUN_GROUP    www-dataENV APACHE_LOG_DIR  /var/log/apache2ENV APACHE_LOCK_DIR /var/lock/apache2ENV APACHE_PID_FILE /var/run/apache2.pidEXPOSE 80EXPOSE 443CMD /usr/sbin/apache2ctl -D FOREGROUND

I'm launching it using the following script :

docker run -ti -d -p 2253:80 -v /home:/home -v /home/antoineb/Docker/images/apache22php53/virtualhosts:/etc/apache2/sites-enabled --name apache22php53 apache22php53 /bin/bash

My websites are stored in /home/website.com/www, and my apache virtualhosts are stored on the host in /home/antoineb/Docker/images/apache22php53/virtualhosts.


Apache 2.4 + PHP 5.6.9 image

Dockerfile :

FROM debian:jessieMAINTAINER AntoineB version: 0.1RUN apt-get update && \    apt-get install -y --force-yes \            apache2 \        php5 \        php5-curl \        php5-gd \        php5-mysql \        nanoRUN a2enmod \            php5 \        rewriteENV APACHE_RUN_USER www-dataENV APACHE_RUN_GROUP    www-dataENV APACHE_LOG_DIR  /var/log/apache2ENV APACHE_LOCK_DIR /var/lock/apache2ENV APACHE_PID_FILE /var/run/apache2.pidEXPOSE 80EXPOSE 443CMD /usr/sbin/apache2ctl -D FOREGROUND

My running script :

docker run -ti -d -p 2456:80 -v /home:/home -v /home/antoineb/Docker/images/apache24php56/virtualhosts:/etc/apache2/sites-enabled --name apache24php56 apache24php56 /bin/bash

Again, my websites are stored in /home/website.com/www, and my apache virtualhosts are stored on the host in /home/antoineb/Docker/images/apache24php56/virtualhosts.


I can't run Apache in the container, since the port 80 is already in use on the host.

Sure you can: in a container, you can run Apache on any port you want.

but when you do docker run, then you need to map this container port to a host port (which won't be 80, since it is already taken, but for instance 8080

docker run -d -p 8080:80 yourImage

My goal would be that the people could access siteA.com, siteB.com, siteC.com and siteZ.com

That is called reverse proxy, and you could run on port 80 a NGiNX (in a container or not) which would then reverse proxy back to siteA, B or C (each running on different port, in container or not).
See for instance "Nginx reverse proxy with multiple ssl domain".

Your main Apache wouldn't run directly on port 80 anymore (or it could, if you put it in a container!)

The goal behind putting everything in its own container is isolation.
Not just filesystem isolation with chroot, or memory isolation, but also configuration isolation: in a container, an Apache always run (if you want) in 80/443, not matter how many Apache containers are running.
You just launch them with the proper host port mapping, but inside a container, the config remains fixed and identical.


You can use host-based routing in docker glue

https://github.com/muayyad-alsadi/docker-glue

it's a light-weight daemon that generates haproxy templates on the fly (you can define nginx template if you like) that watch container labels like this

docker run -d --name wp1 -l glue_http_80_host='wp1.example.com' mywordpress/wordpress docker run -d --name wp2 -l glue_http_80_host='wp2.example.com' mywordpress/wordpress 

in this setup the glue daemon will generate haproxy config so that traffic to wp1.example.com goes to wp1 container