docker-compose пример стека apache2+wsgi, python+django, mysql, phpmyadmin, и проксирование nginx
Создадим с помощью Docker Compose ещё один пример, довольно часто используемый стек: сервер apache2 с python, базой данных на mysql, и контейнер для управления базой с помощью phpmyadmin, а также настроим прокси на nginx ещё в одном отдельном контейнере, чтобы было удобно всем этим пользоваться. Таким образом мы увидим всю логику происходящего, для создания подобных конфигураций, для собственных нужд.
если у вас ещё не установлены docker и docker-compose,
то в Debian подобных дистрибутивах это делается так:
далее для запуска службы, зависит от вашей системы инициализации для систем с systemd
Разрешаем запуск сервиса docker:
systemctl enable docker
... и запускаем его:
systemctl start docker
для MX Linux например с sysV
$ service docker Usage: service docker {start|stop|restart|status} service --status-all service docker start
Совет на будущее, если у вас, что-то не получается при сборке контейнера, то самый лучший и надёжный способ проверить свой алгоритм сборки Dockerfile это создать контейнер из базового образа, который взят за основу, и выполнить вручную последовательность команд и инструкций которые планируется установить при build.
только контейнер должен быть запущен, т.е. иметь активную службу, если это веб сервер, то обычно они запускаются по умолчанию из образа, это нужно, чтобы можно было войти в него.
#изучаем вывод, видим запущен не запущен и получаем id нужного контейнера docker ps -a #смотрим логи "проблемного" контейнера docker logs idconteiner #или сразу заходим внутрь контейнера в его оболочку bash docker exec -it idconteiner bash если у вас есть сложности с пониманием этих моментов, то смотрим инструкции здесь https://www.dmosk.ru/miniinstruktions.php?mini=docker-self-image#backup
На данный момент вы должны просто понимать, как установить docker и как создать контейнер и войти в него в случае такой необходимости. Именно таким образом проб и ошибок, я создавал свою сборку docker-compose для развёртывания приложений на django на веб сервере apache2 через wsgi модуль.
Создаём отдельный рабочий каталог, где мы разместим всю структуру и заходим в этот каталог.
Сперва создаём такую структуру каталогов и файлов, все файлы пока пустые, кроме requirements.txt о котором скажем позже.
Этой командой мы создаём все нужные нам каталоги
mkdir -p html/project_on_django html/logs html/apache_logs html/logs apache mysql nginx/logsПотом уже этой командой создаём все нужные нам файлы
touch nginx/nginx.conf docker-compose.yaml apache/Dockerfile apache/mysite.confИтого, на данный момент, в результате этих двух команды, мы должны иметь вот такую структуру:
команда
☯
Terminal:
⌕
≡
✕
./ ├── apache │ ├── Dockerfile │ └── mysite.conf ├── docker-compose.yaml ├── html │ ├── apache_logs │ ├── logs │ └── project_on_django ├── mysql └── nginx ├── logs └── nginx.conf
Теперь выполняем команды, чтобы создать точно рабочий проект болванку на django.
Сначала переходим в каталог project_on_django.
Итак, вот последовательность команд из корня рабочего каталога:
cd html/project_on_django python -m venv venv . venv/bin/activate pip install django django-admin startproject django_app . python manage.py migrate pip freeze > requirements.txt deactivate #для примера скопируем этот тестовый файл куда нужно, чтобы вы видели всю структуру на выходе mv requirements.txt ../../apache #удаляем не задумываясь окружение, т.к. мы сохранили requirements rm -rf ./venv
как видите мы удалили это временное виртуальное окружение, потому что мы будем создавать новое в контейнере с apache
Это достаточно важный момент, поэтому я считаю, что вы уже из своего реального проекта, из его активного виртуального окружения, сохранили все зависимости в файл, командой:
pip freeze > requirements.txt
Свой файл requirements.txt с зависимости, для вашего будущего окружения python, скопируйте в подкаталог ./apache нашего рабочего каталога
Сейчас возвращаемся в корень рабочего каталога, если с текущего места, то на два каталога выше
в результате получаем примерно такую общую структуру каталогов
☯
Terminal:
⌕
≡
✕
. ├── apache │ ├── Dockerfile │ ├── requirements.txt │ └── mysite.conf ├── docker-compose.yaml ├── html │ ├── apache_logs │ ├── logs │ └── project_on_django │ ├── db.sqlite3 │ ├── django_app │ │ ├── asgi.py │ │ ├── __init__.py │ │ ├── __pycache__ │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ └── manage.py │ ├── mysql └── nginx ├── logs └── nginx.conf
Исходя из этой стандартной структуры проекта на django, мы и будем производить настройку наших будущих контейнеров которые мы сейчас создадим, для выполнения следующих ролей, самый большой и важный контейнер:
- 1)веб сервер apache2 c python окружением и модулем wsgi.
- 2)прокси nginx для работы phpmyadmin и основного адреса сайта, фактически на одном порту для клиента.
- 3)сервер базы данных mysql для работы базы данных.
- 4)контейнер с приложением phpmyadmin, для удобства импорта базы данных.
И общая сеть для связи всех перечисленных контейнеров между собой. Итого у нас будет 4 контейнера у нас будут работать в одной связке.
Имея текущую структуру, и полный порядок, начнём с заполнения файла docker-compose.yaml
☯
Terminal:
⌕
≡
✕
version: '3' services: apache: build: context: ./apache dockerfile: Dockerfile ports: - '88:80' # - '25:25' volumes: - ./html:/var/www/html - ./html/apache_logs:/var/log/apache2 - ./apache/mysite.conf:/etc/apache2/conf-enabled/mysite.conf depends_on: - db environment: - DOMAIN=ramanzes.freemyip.com networks: - myapp_network db: image: mysql:latest volumes: - ./mysql:/var/lib/mysql environment: #естественно, что точно такие же данные подключения, должны быть указаны и в вашем проекте django в файле settings.py #для успешного соединения проекта с этим контейнером баз данных. поэтому можете сразу сюда подставить свои данные из settings.py - MYSQL_DATABASE=u1_database - MYSQL_USER=u1_docker - MYSQL_PASSWORD=Tdasdfsad^234@ - MYSQL_ROOT_PASSWORD=TasdfDD*s232% networks: - myapp_network phpmyadmin: image: phpmyadmin/phpmyadmin ports: - '8088:80' environment: - PMA_ARBITRARY=1 - PMA_HOST=db depends_on: - db networks: - myapp_network proxy: image: nginx:latest volumes: - ./nginx/nginx.conf:/etc/nginx/conf.d/nginx.conf - ./nginx/logs:/var/log/nginx ports: - '80:80' networks: - myapp_network networks: myapp_network: driver: bridge
Как видите директивы volumes фактически пробрасывают каталоги и файлы с хоста, внутрь указанных контейнеров, для того чтобы, например смотреть логи сервера apache, или в случае удаления или новой сборке docker контейнеров, файлы с данными не пострадали, или например для удобной правки файлов сайта проекта прямо на хосте, не заходя внутрь контейнера, для хранения файлов базы данных, конфигураций и т.д. и т.п.. В общем это удобно, поверьте пока на слово, если пока не понимаете всей прелести данного момента.
Если посмотрите на порты, то поймёте, что первый кто будет принимать всех посетителей сайта будет контейнер с nginx потому что он работает на 80 порту, как внешнем так и внутреннем, а затем он уже будет отправлять пользователей либо на наш сайт, в контейнер с apache2 т.е. на 88 порт, либо в контейнер обрабатывающий программу phpmyadmin, это 8088 порт. И за эту процедуру будет отвечать файл nginx/nginx.conf поэтому давайте им и продолжим.
☯
Terminal:
⌕
≡
✕
server { listen 80; listen [::]:80; server_name localhost; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location / { #подставляете свой http://домен:порт proxy_pass http://ramanzes.freemyip.com:88/; } location /phpmyadmin { proxy_pass http://ramanzes.freemyip.com:8088/; } }
В данной конфигурации мы оставили только самое нужное в данном случае. Так как рядовой пользователь всегда приходит на 80 порт по умолчанию, поэтому у нас попадает в контейнер с nginx, в котором, в свою очередь видно, что если в заголовке браузера указана главная страница сайта /, то мы направляем его на 88 порт, т.е. в контейнер с нашим apache. А если в строке браузера мы видим /phpmyadmin, то на порт 8088 т.е. в контейнер с phpmyadmin т.к. он будет работать на этом порту, на нашем хосте с которого он будет пробрасывать запросы на внутренний порт контейнера. Эти порты были указаны в файле
docker-compose.yaml
Теперь рассмотрим наш самый главный в этой связке контейнер, который мы соберём не просто из образа, а с помощью Dockerfile, это и будет наш wsgi веб сервер apache/Dockerfile
☯
Terminal:
⌕
≡
✕
#в качестве базового образа выступает debian 12 FROM debian:12 RUN apt-get update && apt-get upgrade -y && apt-get install -y \ curl apt-utils apt-transport-https debconf-utils gcc build-essential \ python3 python3-pip python3-venv apache2 libapache2-mod-wsgi-py3 \ && a2enmod wsgi && apachectl -M RUN apt-get install -y libpq-dev libonig-dev RUN apt-get install -y locales \ && echo "en_US.UTF-8 UTF-8" > /etc/locale.gen \ && locale-gen # Устанавливается поддержка языковых локалей . RUN apt-get install gettext nano vim -y # Устанавливаются дополнительные утилиты, такие как gettext, nano и vim. # Устанавливаем переменные окружения ENV PYTHONUNBUFFERED 1 # Установка пакетов и зависимостей для Python RUN apt-get install -y python3 # Установка необходимых пакетов для работы с MySQL RUN apt-get install -y default-libmysqlclient-dev # Создание виртуального окружения и активация RUN python3 -m venv /venv #данный каталог /venv создаётся прямо в корне файловой системы ENV PATH="/venv/bin:$PATH" RUN pip3 install --upgrade pip RUN pip3 install pyodbc # Устанавливается модуль pyodbc для подключения к базам данных SQL Server. #подключить дополнительные репозитории для установки пакета XVFB в Debian контейнере RUN echo "deb http://deb.debian.org/debian buster-backports main" >> /etc/apt/sources.list RUN echo "deb http://deb.debian.org/debian buster main contrib non-free" >> /etc/apt/sources.list RUN echo "deb http://deb.debian.org/debian buster-updates main contrib non-free" >> /etc/apt/sources.list #Установите зависимости для сборки пакета Pillow. RUN apt-get update && apt-get install -y xvfb RUN apt-get install -y libjpeg-dev zlib1g-dev libtiff5-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev #на данном этапе у вас уже должен быть файл с зависимости окружения в каталоге apache и там есть requirements.txt COPY ./requirements.txt ./requirements.txt RUN pip3 install --no-cache-dir -r ./requirements.txt # Копирование конфигурационных файлов Apache (если требуется) # COPY apache2.conf /etc/apache2/apache2.conf # COPY 000-default.conf /etc/apache2/sites-available/000-default.conf # нам это не требуется, мы подключим свой файл конфигурации mysite.conf с хоста через volumes # Очистка кэша apt-get и временных файлов RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN echo "deb http://deb.debian.org/debian buster-backports main contrib non-free" >> /etc/apt/sources.list RUN echo "deb http://deb.debian.org/debian buster-backports-sloppy main contrib non-free" >> /etc/apt/sources.list RUN apt-get update RUN a2enmod headers && a2enmod wsgi RUN apachectl -M | grep headers RUN apachectl -M | grep wsgi #RUN apache2 -k graceful # установим владельцем окружения python пользователя apache т.е. www-data RUN chown -R www-data:www-data /venv #RUN a2enconf mysite # Открытие порта 80 для Apache EXPOSE 80 #EXPOSE 80 88 8000 # Команда для запуска Apache внутри контейнера CMD ["apache2ctl", "-D", "FOREGROUND"]
теперь сразу рассмотрим ещё один важный файл apache/mysite.conf, который будет настройкой нашего веб сервера на работу через WSGI модуль.
☯
Terminal:
⌕
≡
✕
<VirtualHost *:80> # Описание сервера ServerAdmin email@mail.ru # домен сайта ServerName apache #ServerAlias www.dp DocumentRoot /var/www/html/project_on_django ErrorLog /var/www/html/logs/error_log CustomLog /var/www/html/logs/access_log common Alias /static /var/www/html/project_on_django/static <Directory /var/www/html/project_on_django/static> Require all granted </Directory> Alias /images /var/www/html/project_on_django/static/images <Directory /var/www/html/project_on_django/static/images> Require all granted </Directory> <Directory /var/www/html/project_on_django/django_app> <Files wsgi.py> Require all granted </Files> </Directory> #указываем имя процессу nameD, потом через пробел, путь к проекту, и через пробел, указываем путь к окружению python у нас это корень диска /venv WSGIDaemonProcess nameD python-path=/var/www/html/project_on_django python-home=/venv WSGIProcessGroup nameD #здесь указываем путь к файлу wsgi.py нашего проекта WSGIScriptAlias / /var/www/html/project_on_django/django_app/wsgi.py </VirtualHost>
Фактически мы указали все нужные нам настройки и готовы к сборке и запуску проекта, находясь в корне рабочего каталога, а точнее на том же уровне где и наш файл docker-compose.yaml начинаем выполнять команды.
#загрузим все образы к себе а сервер
#создадим сборку
#запустим сборку
#проверим результат
на каждой команде смотрим вывод, на наличие ошибок, всё должно пройти без ошибок, в противном случае вносим соответствующие исправления до получения желаемого результата.
в результате docker ps -a мы должны увидеть все контейнеры, причём все 4, которые мы здесь создали, должны быть в состоянии up, но если какой то из них не up, то смотрим логи именно этого контейнера, командой
docker logs f3f99f5156dd
где указываем id контейнера, возможно вы забыли выставить нужные права на каталоги или ошиблись в путях, например я здесь в файле mysite.conf, для примера указывал ошибочный путь для записей логов, и вот что получил в этом случае в логах остановленного контейнера apache.
☯
Terminal:
⌕
≡
✕
root@host:~/docker/django/test# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0d0e6c7a4092 phpmyadmin/phpmyadmin "/docker-entrypoint.…" 5 minutes ago Up 5 minutes 0.0.0.0:8088->80/tcp, :::8088->80/tcp test_phpmyadmin_1 f3f99f5156dd test_apache "apache2ctl -D FOREG…" 5 minutes ago Exited (0) 88/tcp, 8000/tcp, 0.0.0.0:88->80/tcp, :::88->80/tcp test_apache_1 5 minutes ago d2275bfae6f4 nginx:latest "/docker-entrypoint.…" 5 minutes ago Up 5 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp test_proxy_1 c6a597676044 mysql:latest "docker-entrypoint.s…" 5 minutes ago Up 5 minutes 3306/tcp, 33060/tcp test_db_1 root@host:~/docker/django/test# docker logs f3f99f5156dd AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 192.168.0.5. Set the 'ServerName' directive globally to suppress this message (2)No such file or directory: AH02291: Cannot access directory '/var/www/html/project_on_django/logs/' for error log of vhost defined at /etc/apache2/conf-enabled/mysite.conf:1 AH00014: Configuration check failed Action '-D FOREGROUND' failed. The Apache error log may have more information.
а если, к примеру, вместо проекта вы видите файлы проекта, то во первых ваш nginx и даже apache у вас уже работают правильно, но скорее всего ваша конфигурация mysite.conf по каким то причинам, не подключена, проверьте ещё раз все указанные пути.
если вы видите вот это, это значит хоть прокси сервер и работает, но ваша конфигурация nginx.conf не была подключена - проверьте пути подключения или сам файл настроек.
итак, сделав нужные исправления в файле mysite.conf и запустив браузер, снова вводим свой адрес, чтобы получить желаемое, но если вдруг мы получили что-то вроде этого:
то вы знаете, что нужно указать свой домен,в качестве разрешённых, в файле settings.py своего проекта, чтобы получить например вот это
-
- Roman Sakhno
Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.