Проект Docker работает намного медленнее

#php #mysql #docker #nginx #docker-compose

#php #mysql #docker #nginx #docker-compose

Вопрос:

Что я сделал, так это перевел проект на работу с контейнерами docker. Проект довольно большой, и в итоге у меня получилось около 12 контейнеров.

И теперь на данный момент есть 2 идентичных сервера под управлением Ubuntu 18.04.

  1. На первом сервере проект развертывается как обычно: запускаются Nginx, PHP7.2-fpm, MySQL5.7 и другие сервисы.
  2. На втором сервере проект был поднят на docker

Суть проблемы в том, что при тестировании скорости обработки нескольких запросов на обоих серверах сервер в docker показывает гораздо худшую производительность.

Вот проект на исходном сервере (тест с ApacheBench n100 c100):

 Server Software:        nginx
Server Hostname:        test.com
Server Port:            443
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128
TLS Server Name:        test.com
Document Path:          /
Document Length:        119121 bytes

Concurrency Level:      100
Time taken for tests:   1.827 seconds
Complete requests:      100
Failed requests:        0
Total transferred:      12038500 bytes
HTML transferred:       11912100 bytes
Requests per second:    54.74 [#/sec] (mean)
Time per request:       1826.828 [ms] (mean)
Time per request:       18.268 [ms] (mean, across all concurrent requests)
Transfer rate:          6435.39 [Kbytes/sec] received

Connection Times (ms)
              min  mean[ /-sd] median   max
Connect:      144  152   4.4    152     160
Processing:    50  899 469.8    938    1660
Waiting:       48  896 469.7    936    1658
Total:        203 1051 473.8   1090    1819

Percentage of the requests served within a certain time (ms)
  50%   1090
  66%   1330
  75%   1458
  80%   1550
  90%   1702
  95%   1770
  98%   1815
  99%   1819
 100%   1819 (longest request)
 

Вот проект docker (тест с ApacheBench n100 c100):

 Server Software:        nginx/1.19.1
Server Hostname:        test-dev.com
Server Port:            443
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128
TLS Server Name:        test-dev.com

Document Path:          /
Document Length:        724822 bytes

Concurrency Level:      100
Time taken for tests:   12.573 seconds
Complete requests:      100
Failed requests:        99
   (Connect: 0, Receive: 0, Length: 99, Exceptions: 0)
Non-2xx responses:      100
Total transferred:      72592310 bytes
HTML transferred:       72476910 bytes
Requests per second:    7.95 [#/sec] (mean)
Time per request:       12572.860 [ms] (mean)
Time per request:       125.729 [ms] (mean, across all concurrent requests)
Transfer rate:          5638.41 [Kbytes/sec] received

Connection Times (ms)
              min  mean[ /-sd] median   max
Connect:      135  140   3.4    140     146
Processing:  1351 8110 3454.4  10254   12421
Waiting:     1338 8066 3443.4  10211   12416
Total:       1486 8250 3457.5  10397   12566

Percentage of the requests served within a certain time (ms)
  50%  10397
  66%  10789
  75%  11078
  80%  11260
  90%  11801
  95%  12334
  98%  12519
  99%  12566
 100%  12566 (longest request)
 

Я уже просмотрел множество руководств, статей и прочего. Перепробовал много советов. Ничего не помогает.

  1. Переделка новой работы в docker
  2. Отключен отладчик в php
  3. Использовались разные версии docker-compose
  4. Правила настройки docker deamon

Все действия привели к достаточно хорошей скорости для одного пользователя. Но под нагрузкой docker работает просто ужасно медленно.

Вот docker-compose.yml (PHP, Mysql, Nginx расположены в задней части):

 version: '3'

volumes:
  dump:

services:

  # ------------- Front --------------

  # project base ------------------------------------
  bb_base:
    build:
      context: ../front/project-base
      dockerfile: Dockerfile
      args:
        - WORKDIR=${BB_BASE_WORKDIR}
    container_name: ${BB_BASE_WORKDIR}
    restart: always
    working_dir: /var/www/${BB_BASE_WORKDIR}
    volumes:
      - ../front/project-base:/var/www/${BB_BASE_WORKDIR}
  # project ui-kit ----------------------------------
  bb_ui-kit:
    build:
      context: ../front/project-ui-kit
      dockerfile: Dockerfile
      args:
        - WORKDIR=${BB_UI_KIT_WORKDIR}
    container_name: ${BB_UI_KIT_WORKDIR}
    restart: always
    working_dir: /var/www/${BB_UI_KIT_WORKDIR}
    volumes:
      - ../front/project-ui-kit:/var/www/${BB_UI_KIT_WORKDIR}
      - ../front/project-base:/var/www/${BB_BASE_WORKDIR}
    command: sh /var/www/${BB_UI_KIT_WORKDIR}/entrypoint.sh
    depends_on:
      - bb_base
  # project auth ----------------------------------
  bb_auth:
    build:
      context: ../front/project-auth
      dockerfile: Dockerfile
      args:
        - WORKDIR=${BB_AUTH_WORKDIR}
    container_name: ${BB_AUTH_WORKDIR}
    restart: always
    working_dir: /var/www/${BB_AUTH_WORKDIR}
    volumes:
      - ../front/project-auth:/var/www/${BB_AUTH_WORKDIR}
      - ../front/project-base:/var/www/${BB_BASE_WORKDIR}
      - ../front/project-ui-kit:/var/www/${BB_UI_KIT_WORKDIR}
    command: sh /var/www/${BB_AUTH_WORKDIR}/entrypoint.sh
    depends_on:
      - bb_ui-kit
  # project crm ----------------------------------
  bb_crm:
    build:
      context: ../front/project-crm
      dockerfile: Dockerfile
      args:
        - WORKDIR=${BB_CRM_WORKDIR}
    container_name: ${BB_CRM_WORKDIR}
    restart: always
    working_dir: /var/www/${BB_CRM_WORKDIR}
    volumes:
      - ../front/project-crm:/var/www/${BB_CRM_WORKDIR}
      - ../front/project-base:/var/www/${BB_BASE_WORKDIR}
      - ../front/project-ui-kit:/var/www/${BB_UI_KIT_WORKDIR}
    command: sh /var/www/${BB_CRM_WORKDIR}/entrypoint.sh
    depends_on:
      - bb_ui-kit
  # project link ----------------------------------
  bb_link:
    build:
      context: ../front/project-link
      dockerfile: Dockerfile
      args:
        - WORKDIR=${BB_LINK_WORKDIR}
    container_name: ${BB_LINK_WORKDIR}
    restart: always
    working_dir: /var/www/${BB_LINK_WORKDIR}
    volumes:
      - ../front/project-link:/var/www/${BB_LINK_WORKDIR}
      - ../front/project-base:/var/www/${BB_BASE_WORKDIR}
      - ../front/project-ui-kit:/var/www/${BB_UI_KIT_WORKDIR}
    command: sh /var/www/${BB_LINK_WORKDIR}/entrypoint.sh
    depends_on:
      - bb_ui-kit

  # --------------- Back ----------------

  # PHP -----------------------------------------------
  bb_php:
    user: "${USER_ID}:1000"
    build:
      context: ../back/project-back/images/php
      dockerfile: Dockerfile
      args:
        - DOMAIN=${DOMAIN}
        - ENV=${DOCKER_ENV}
    container_name: ${BB_PHP_WORKDIR}
    restart: always
#    ports:
#      - "${PORT_PHP}:9000"
    working_dir: /var/www/${BB_PHP_WORKDIR}
    volumes:
      - ../back/project-back:/var/www/${BB_PHP_WORKDIR}
      #- photos:/var/www/${BB_PHP_WORKDIR}/storage/app/photos-mount
    depends_on:
      - bb_mysql
  # Nginx -----------------------------------------------
  bb_nginx:
    build:
      context: ../back/project-back/images/nginx
      dockerfile: Dockerfile
      args:
        - DOMAIN=${DOMAIN}
        - ENV=${DOCKER_ENV}
        - BACK_DIR=${BB_PHP_WORKDIR}
        - LOCAL_DIR=${BB_NGINX_WORKDIR}
        - LINK_DIR=${BB_LINK_WORKDIR}
        - AUTH_DIR=${BB_AUTH_WORKDIR}
        - CRM_DIR=${BB_CRM_WORKDIR}
    container_name: ${BB_NGINX_WORKDIR}
    restart: always
    ports:
      - "${PORT_HTTP}:80"
      - "${PORT_HTTPS}:443"
    working_dir: /var/www/${BB_NGINX_WORKDIR}
    volumes:
      - ../back/project-back:/var/www/${BB_NGINX_WORKDIR}
      - ../front/project-crm:/var/www/${BB_CRM_WORKDIR}
      - ../front/project-auth:/var/www/${BB_AUTH_WORKDIR}
      - ../front/project-link:/var/www/${BB_LINK_WORKDIR}
    depends_on:
      - bb_php
  # MySQL -------------------------------------------------
  bb_mysql:
    image: gitlab.project.ru:5050/project/backend/project/mysql:1.0
    container_name: ${BB_MYSQL_WORKDIR}
    restart: always
    tty: true
    ports:
      - "${PORT_MYSQL}:3306"
    volumes:
      - dump:/var/lib/mysql
      - ../back/project-back/images/mysql/mysql.cnf:/etc/mysql/conf.d/mysql.cnf
      - ../back/project-back/images/mysql/mysqldump.cnf:/etc/mysql/conf.d/mysqldump.cnf
      - ../back/project-back/images/mysql/optimize.cnf:/etc/mysql/conf.d/optimize.cnf
    env_file:
      - ../back/project-back/.env
  # Redis -------------------------------------------------
  bb_redis:
    image: redis:6-alpine
    container_name: ${BB_REDIS_WORKDIR}
    restart: always
#    ports:
#      - "${PORT_REDIS}:6379"
    volumes:
      - ../back/project-back/images/redis/redis.conf:/redis.conf
    depends_on:
      - bb_php
      - bb_mysql
    command: [ "redis-server", "/redis.conf" ]
  # Mysql-cron-backup --------------------------------------
  bb_mysql_cron_backup:
    build:
      context: ../back/project-back/images/mysql-cron-backup
      dockerfile: Dockerfile
    container_name: ${BB_MYSQL_CRON_BACKUP}
    restart: always
    volumes:
      - ${VOLUME_PATH}/backup:/backup
    environment:
      - MAX_BACKUPS=${MAX_BACKUPS}
      - INIT_BACKUP=0
      - CRON_TIME=*/15 * * * *
      - GZIP_LEVEL=9
    depends_on:
      - bb_mysql
    env_file:
      - ../back/project-back/.env

  # --------------- Services -------------

  # Socket -----------------------------------------------
  bb_socket:
    build:
      context: ../back/project-services/project-sockets
      dockerfile: Dockerfile
    container_name: ${BB_SOCKETS_WORKDIR}
    restart: always
    working_dir: /var/www/${BB_SOCKETS_WORKDIR}
    volumes:
      - ../back/project-services/project-sockets:/var/www/${BB_SOCKETS_WORKDIR}
  # Recommend products ------------------------------------
  bb_recommend:
    image: prod_rec:latest
    build:
      context: ../back/project-services/project-recommendation
      dockerfile: Dockerfile
    container_name: ${BB_RECCOMEND_WORKDIR}
    restart: always
    ports:
      - "${PORT_RP}:5000"
    environment:
      - FLASK_APP=${FLASK_APP}
      - FLASK_DEBUG=${FLASK_DEBUG}
      - SECRET_KEY=${SECRET_KEY}
      - DATABASE_URL_APP=${DATABASE_URL_APP}
      - DATABASE_URL_PROD=${DATABASE_URL_PROD}
    volumes:
      - ../back/project-services/project-recommendation/config.py:/home/prod_rec/config.py
      - ../back/project-services/project-recommendation/app.py:/home/prod_rec/app.py
      - ../back/project-services/project-recommendation/app:/home/prod_rec/app
      - ../back/project-services/project-recommendation/migrations:/home/prod_rec/migrations
    depends_on:
      - bb_recommend_mysql
    links:
      - bb_recommend_mysql:dbserver
  # Recommend products MySQL ------------------------------------
  bb_recommend_mysql:
    image: mysql/mysql-server:5.7
    container_name: ${BB_RECCOMEND_MYSQL_WORKDIR}
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=${RP_MYSQL_ROOT_PASSWORD}
      - MYSQL_DATABASE=${RP_MYSQL_DATABASE}
      - MYSQL_USER=${RP_MYSQL_USER}
      - MYSQL_PASSWORD=${RP_MYSQL_MYSQL_PASSWORD}
    volumes:
      - ../back/project-services/project-recommendation/my.cnf:/etc/my.cnf:ro
  # Cdek ----------------------------------------------
  bb_cdek:
    image: cdek:latest
    build:
      context: ../back/project-services/project-cdek
      dockerfile: Dockerfile
    container_name: ${BB_CDEK_WORKDIR}
    restart: always
    ports:
      - "${PORT_CDEK}:8080"
    env_file:
      - ../back/project-services/project-cdek/.env
    environment:
      - DEBUG_VALUE=FALSE
    volumes:
      - ../back/project-services/project-cdek/flask_api.py:/home/cdek/cdek/flask_api.py
      - ../back/project-services/project-cdek/boot.sh:/home/cdek/cdek/boot.sh
  # MoySklad -----------------------------------------------
  bb_moysklad:
    image: moysklad:latest
    build:
      context: ../back/project-services/project-moysklad
      dockerfile: Dockerfile
    container_name: ${BB_MOYSKLAD_WORKDIR}
    restart: always
    ports:
      - "${PORT_MOYSKLAD}:5000"
    environment:
      - QUART_APP=${QUART_APP}
      - QUART_DEBUG=${QUART_DEBUG}
      - SECRET_KEY=${MS_SECRET_KEY}
      - ENV=${MS_ENV}
    volumes:
      - ../back/project-services/project-moysklad/app.py:/home/moysklad/app.py
      - ../back/project-services/project-moysklad/webhook.log:/home/moysklad/webhook.log
      - ../back/project-services/project-moysklad/async_file.py:/home/moysklad/async_file.py
      - ../back/project-services/project-moysklad/config.py:/home/moysklad/config.py
      - ../back/project-services/project-moysklad/start.py:/home/moysklad/start.py
 

Ну, в этом-то и проблема. Как решить проблему в скорости при высокой нагрузке на проект? Почему docker работает так медленно под нагрузкой? Есть идеи?

Если вам нужны дополнительные данные, я приложу их.

Комментарии:

1. Какого облачного провайдера вы используете? Используете ли вы VPS, управляемый самостоятельно?

2. Ограничивает ли ваш драйвер cgroup ресурсы контейнера? Вы можете запустить docker stats , чтобы увидеть показатели времени выполнения и, если настроено, ограничения ресурсов. Для лучшего мониторинга вы можете использовать cAdvisor для сбора статистики использования Prometheus из ваших контейнеров Docker. Кроме того, вы можете использовать Prometheus exporters для Nginx и MySQL, чтобы увидеть их поведение при запуске в разных средах.

3. Похоже, вы пытаетесь использовать гибридную настройку, в которой вы переместили интерпретатор PHP внутрь уровня изоляции Docker, но все еще пытаетесь использовать свой хост-код. Удаляет ли большую часть volumes: справочной производительности? (Есть похожие вопросы, особенно о производительности PHP как на macOS, так и на WSL.)