Docker - запуск Apache на хосте и контейнере для разных сайтов

Я хочу использовать Docker, чтобы иметь возможность запускать старое приложение, для которого требуется PHP 5.3, при этом у меня еще есть другие сайты на моем хост-сервере, запущенные на хосте Apache.

Итак, у меня есть siteA.com, siteB.com, siteC.com, работающий на хосте, с использованием сервера Apache/PHP/MySQL хоста, и у меня есть siteZ.com, который установлен в контейнер Docker, который должен использоваться контейнер Apache/PHP, но сервер MySQL хоста.

Здесь представлено представление архитектуры, которую я хотел бы получить:

Представление моей архитектуры

Моя проблема в том, что кажется, что я не могу запустить Apache в контейнере, поскольку порт 80 уже используется на хосте.

Моя цель состояла бы в том, чтобы люди могли получить доступ к сайтам site.com, siteB.com, siteC.com и siteZ.com, не указав другой порт для любого из этих сайтов.

Мне удалось запустить siteZ.com, используя порт 8080, но это явно не вариант.

Спасибо

PS: Обратите внимание, что я полностью новичок в Docker.

Изменить: вы можете найти мое рабочее решение здесь. Спасибо VonC за показывая мне путь:)

Ответ 1

Благодаря VonC answer Мне удалось заставить его работать, но я немного изменил свою архитектуру, в результате чего было создано 3 контейнера вместо 1.

У меня есть один контейнер для каждой версии Apache/PHP и один контейнер с Nginx как обратный прокси. Я думаю, вы можете легко адаптировать это, чтобы установить Nginx на хост и изменить его конфигурацию в соответствии с архитектурой, описанной в моем вопросе.

Обратите внимание, что, поскольку я новичок в Docker и noob относительно системного администрирования Linux, их, вероятно, некоторые ошибки и вещи, которые не имеют никакого смысла в следующих сценариях, но это работает для меня. Не стесняйтесь его улучшать:)


Обратное прокси-изображение Nginx

Файл Docker:

FROM debian:jessie

MAINTAINER AntoineB version: 0.1

RUN apt-get update && \
    apt-get install -y --force-yes \
            nginx \
        nano

EXPOSE 80
EXPOSE 443

ADD ./proxy.conf /etc/nginx/conf.d/proxy.conf

CMD ["nginx"]

Здесь указан файл proxy.conf:

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;

И я запускаю его, используя следующий 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

У меня есть папка /home/antoineb/Docker/images/nginxproxy/virtualhosts на моем хосте, которая содержит следующий default файл:

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

Файл докеров:

FROM debian:wheezy

MAINTAINER AntoineB version: 0.1

RUN apt-get update

RUN echo "deb http://packages.dotdeb.org squeeze all" > /etc/apt/sources.list.d/dotdeb_squeeze.list
RUN echo "deb-src http://packages.dotdeb.org squeeze all" >> /etc/apt/sources.list.d/dotdeb_squeeze.list
RUN echo "deb http://ftp.debian.org/debian/ squeeze main contrib non-free" >> /etc/apt/sources.list.d/dotdeb_squeeze.list

RUN echo "Package: *php*" > /etc/apt/preferences.d/php53.pref
RUN echo "Pin: release o=packages.dotdeb.org,n=squeeze" >> /etc/apt/preferences.d/php53.pref
RUN echo "Pin-Priority: 989" >> /etc/apt/preferences.d/php53.pref

RUN apt-get update && \
    apt-get install -y --force-yes \
            apache2 \
        php5 \
        php5-curl \
        php5-gd \
        php5-mysql \
        nano

RUN a2enmod \
            php5 \
        rewrite

ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP    www-data
ENV APACHE_LOG_DIR  /var/log/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2
ENV APACHE_PID_FILE /var/run/apache2.pid

EXPOSE 80
EXPOSE 443

CMD /usr/sbin/apache2ctl -D FOREGROUND

Я запускаю его, используя следующий 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

Мои сайты хранятся в /home/website.com/www, а мои виртуальные хосты apache хранятся на хосте в /home/antoineb/Docker/images/apache22php53/virtualhosts.


Apache 2.4 + PHP 5.6.9 image

Файл докеров:

FROM debian:jessie

MAINTAINER AntoineB version: 0.1

RUN apt-get update && \
    apt-get install -y --force-yes \
            apache2 \
        php5 \
        php5-curl \
        php5-gd \
        php5-mysql \
        nano

RUN a2enmod \
            php5 \
        rewrite

ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP    www-data
ENV APACHE_LOG_DIR  /var/log/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2
ENV APACHE_PID_FILE /var/run/apache2.pid

EXPOSE 80
EXPOSE 443

CMD /usr/sbin/apache2ctl -D FOREGROUND

Мой запуск 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

Снова мои сайты хранятся в /home/website.com/www, а мои виртуальные хосты apache хранятся на хосте в /home/antoineb/Docker/images/apache24php56/virtualhosts.

Ответ 2

Я не могу запустить Apache в контейнере, поскольку порт 80 уже используется на хосте.

Конечно, вы можете: в контейнере вы можете запустить Apache на любом порту, который вам нужен.

но когда вы выполняете docker run, вам необходимо сопоставить порт этого контейнера с портом хоста (который не будет равен 80, поскольку он уже выполнен, но, например, 8080

docker run -d -p 8080:80 yourImage

Моя цель состояла бы в том, чтобы люди могли получить доступ к сайтам site.com, siteB.com, siteC.com и siteZ.com

Это называется обратным прокси-сервером, и вы можете запускать на порт 80 NGiNX (в контейнере или нет), который затем будет отбрасывать прокси обратно на сайтA, B или C (каждый из них выполняется на другом порту, в контейнере или нет).
См. Например "обратный прокси Nginx с несколькими доменами ssl.

Ваш основной Apache больше не будет запускаться непосредственно на порт 80 (или он может, если вы поместите его в контейнер!)

Целью размещения всего в собственном контейнере является изоляция.
Не только изоляция файловой системы с chroot, либо изоляция памяти, но и изоляция конфигурации: в контейнере Apache всегда запускается (если хотите) в 80/443, неважно, сколько контейнеров Apache запущено.
Вы просто запускаете их с правильным отображением портов хоста, но внутри контейнера конфиг остается фиксированным и идентичным.

Ответ 3

Вы можете использовать маршрутизацию на основе хоста в докерном клеве

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

это легкий демон, который генерирует шаблоны haproxy "на лету" (вы можете определить шаблон nginx, если хотите), которые наблюдают за такими ярлыками контейнера

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 

в этой настройке демон glue будет генерировать конфигурацию haproxy, чтобы трафик на wp1.example.com переходил в контейнер wp1