Bootstrap

docker-compose пример стека apache2+wsgi, python+django, mysql, phpmyadmin, и проксирование nginx

docker-compose пример стека apache2+wsgi, python+django, mysql, phpmyadmin, и проксирование nginx

Создадим с помощью Docker Compose ещё один пример, довольно часто используемый стек: сервер apache2 с python, базой данных на mysql, и контейнер для управления базой с помощью phpmyadmin, а также настроим прокси на nginx ещё в одном отдельном контейнере, чтобы было удобно всем этим пользоваться. Таким образом мы увидим всю логику происходящего, для создания подобных конфигураций, для собственных нужд.

если у вас ещё не установлены docker и docker-compose,

 

то в Debian подобных дистрибутивах это делается так:


sudo apt update

sudo apt install docker docker.io

sudo apt install docker-compose

далее для запуска службы, зависит от вашей системы инициализации для систем с 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
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
touch nginx/nginx.conf docker-compose.yaml apache/Dockerfile apache/mysite.conf

Итого, на данный момент, в результате этих двух команды, мы должны иметь вот такую структуру:

команда


tree ./

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 нашего рабочего каталога

Сейчас возвращаемся в корень рабочего каталога, если с текущего места, то на два каталога выше


cd ../../

в результате получаем примерно такую общую структуру каталогов


tree -L 4 ./

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 начинаем выполнять команды.

#загрузим все образы к себе а сервер


sudo docker-compose pull

#создадим сборку


sudo docker-compose build

#запустим сборку


sudo docker-compose up -d

#проверим результат


sudo docker ps -a

на каждой команде смотрим вывод, на наличие ошибок, всё должно пройти без ошибок, в противном случае вносим соответствующие исправления до получения желаемого результата.

в результате 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 и даже apache у вас уже работают правильно, но не учтены настройки mysite.conf

если вы видите вот это, это значит хоть прокси сервер и работает, но ваша конфигурация nginx.conf не была подключена - проверьте пути подключения или сам файл настроек.

наверное конфигурация nginx.conf не подключена

итак, сделав нужные исправления в файле mysite.conf и запустив браузер, снова вводим свой адрес, чтобы получить желаемое, но если вдруг мы получили что-то вроде этого:

allow host должен быть указан в настройках сайта

то вы знаете, что нужно указать свой домен,в качестве разрешённых, в файле settings.py своего проекта, чтобы получить например вот это

успех развёртывания django в docker на apache с wsgi модулем

Копирование материалов разрешается только с указанием автора Roman Sakhno и индексируемой прямой ссылкой на сайт (http://itdid.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/sahroman.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/sahroman.

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как настроить свой компьютер

  2. Текстовая ссылка:

    Она выглядит вот так: Как настроить свой компьютер

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

Комментарии (0):

Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.

крипто-донат, на развитие сайта itdid.ru:

В новом окне с терминалом itdid.ru, введите любую сумму: