angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

ISPConfig: Управление Python Flask Docker контейнером как заключенным пользователем "Шелл".

Описанный метод требует, чтобы вы были root, то есть не универсальным, но может быть достаточным, если вы являетесь системным администратором.

18 октября 2019 Обновленный 18 октября 2019
post main image
unsplash.com/@emilydafinchy

Я управляю сервером с 50 сайтами. Вы можете создавать виртуальные среды на ISPConfig сервере и ISPConfig запускать свои приложения отсюда, но некоторое время назад я решил использовать Python Flask их для разработки и производства. staging На это уходит время, но это того стоит. Docker Так держать.

Я воспользуюсь заключенным пользователем Shell для управления контейнером. Причина в том, что когда контейнер прерывает доступ ограничивается правами пользователя Shell в тюрьме, не так ли? См. также Резюме ниже.

Моя система

  • ISPConfig3 3.1.13
  • Debian 9 (Растягивание)
  • MariaDB 10.3
  • Nginx 1.10.3

Мой Docker контейнер на ISPConfig

Для производства Python Flask Docker контейнера, основанного на Alpine и содержащего приложение и веб сервер Gunicorn WSGI, используется отображение "томов" для файлов журналов, файлов сеансов и кэш-памяти. Кроме того, он содержит отображение "томов" в статический каталог.

Для разработки и производства я использую файл .dockerignore, чтобы исключить статическую папку из каталога Docker image. Он быстро растет со всеми изображениями. Для развития он нам все равно не нужен, так как мы обслуживаем все, что находится за пределами Docker контейнера. Для производства мы также не хотим, чтобы статическая папка в контейнере оставалась неподвижной. Здесь мы обслуживаем статические элементы не с, а непосредственно с Nginx.

Docker Python Flask Контейнер не содержит базы данных и т.д., но использует ISPConfig сервисы для простой настройки и управления:

  • Управление ISPConfig доменом и сайтами (включая шифрование SSL)
  • База данных хоста (MariaDB), подключение через разъем ( )
  • Почта хоста (Postfix), соединитесь с сервером через port 25
  • Веб-сервер хозяина (Nginx), обратный и обслуживающий статический сервер ( )

Обратите внимание, что я собираю Docker image на своей локальной машине, используя ее:

docker save ...

Полученный tar-файл копируется на ISPConfig сервер и распаковывается, см. ниже.

Для настройки под наш сайт мы делаем все как обычно:

  • Установка Docker и компоновка (только один раз)
  • Добавить домен
  • Добавить веб-сайт, установить Позволяет шифровать SSL
  • Добавить пользователя базы данных и базы данных
  • Добавьте заключенного (!) Пользователя раковины, Chroot Shell: Тюрьма

Каталоги по ISPConfig, пользователям и группам

Когда мы добавили сайт (и создали оболочку), для него был ISPConfig создан пользователь (Linux), мой пользователь Shell:

  • Имя пользователя: peterpepepyco

Пользователь и группа linux, см. раздел ISPConfig -> Shell User -> Options, в моем случае:

  • Имя пользователя: web73
  • Web Group: клиент2

Вы также можете увидеть это, войдя в систему с Shell User и пройдя через некоторые директории, сделав 'ls -n'.

Существует разница между заключенным в тюрьму пользователем Shell и не заключенным в тюрьму пользователем Shell. В обоих случаях базовой директорией является директория:

/var/www/clients/client2/web73

Домашний каталог:

/var/www/clients/client2/web73/home/peterpepyco

и веб-каталог:

/var/www/clients/client2/web73/web

Когда Shell User находится в тюрьме, корень файловой системы меняется на базовый каталог.для получения группы типа Shell User:

groups

который возвращается в моем случае:

client2

Для запуска в Docker качестве другого пользователя нам необходимы идентификатор пользователя, UID и идентификатор группы, GID. Чтобы получить тип UID:

id -u

который возвращается в моем случае 5055, и...:

id -g

который возвращается в моем случае 5006. Есть много способов получить UID и GID. Вы также можете печатать:

cat /etc/passwd

который возвращается:

root:x:0:0:root:/root:/bin/bash
peterpepyco:x:5055:5006:::/bin/bash

и

cat /etc/group

который возвращается:

root:x:0:
client2:x:5006:

Вы также можете создать файл, "echo " > a", а затем сделать 'ls -n' и т.д.

Изменение Nginx конфигурации

ISPConfig Зайдите на сайт и выберите вкладку Параметры. В разделе Nginx Директивы вставить:

 location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    client_max_body_size 1M;  
  }

  location /static {
    alias /var/www/clients/client2/web73/web/static;
  }

Обратите внимание, что запросы в порт 8000 передаются в обратном порядке. Это порт, который прослушивает Gunicorn WSGI-сервер в контейнере.

Копирование файлов

В Shell User home я создаю докер директорий, куда копирую сжатый контейнер, файл переменных окружения, docker-compose файлы и базу данных. После копирования каталог выглядит следующим образом:

.
└── docker
    ├── .env
    ├── docker-compose_base_1.283_production.yml
    ├── docker-compose_production.yml
    ├── docker-volumes
    │   ├── cache
    │   │   ├── other
    │   │   ├── query_result
    │   │   └── render_template
    │   ├── flask_session
    │   └── log
    ├── peterspython2.dump_20191017
    ├── peterspython_image_web_1.283.tar
    └── project
        ├── Dockerfile
        └── requirements.txt

Для загрузки базы данных:

mysql -upeterspythonuser -p peterspython2 < peterspython2.dump_20191017

Чтобы загрузить изображение доккера, необходимо, чтобы вы были root:

docker load -i peterspython_image_web_1.283.tar

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

Добавление пользователя, UID и группы, GID, в и Dockerфайл

Я использую Docker-compose для запуска и остановки контейнера, томов карты и т.д. Файл .env содержит ряд переменных конфигурации, которые мы передаем в . Первая часть этого файла:

# production environment vars

PROJECT_NAME=peterspython

FLASK_CONFIG=production

# docker-compose, docker
# peterpepyco:client2
CONTAINER_USER=peterpepyco
CONTAINER_UID=5055
CONTAINER_GROUP=client2
CONTAINER_GID=5006
...

Первая часть композиционного файла:

# docker-compose_base.yml

version: '3.2'

services:
  web:
    image: ${PROJECT_NAME}_image_web:1.283
    container_name: ${PROJECT_NAME}_container_web
    env_file:
      - ./.env
    restart: always
    build:
      context: ./project
      dockerfile: Dockerfile
      args:
        - CONTAINER_USER=${CONTAINER_USER}
        - CONTAINER_UID=${CONTAINER_UID}
        - CONTAINER_GROUP=${CONTAINER_GROUP}
        - CONTAINER_GID=${CONTAINER_GID}

    ports:
      - "${SERVER_PORT_HOST}:${SERVER_PORT_CONTAINER}"
    volumes:
...

а затем в Dockerдосье:

...
# create and set working directory
RUN mkdir -p /home/flask/project
WORKDIR /home/flask/project

# copy app code into container
COPY . ./

# create group and user used in this container
ARG CONTAINER_USER
ARG CONTAINER_UID
ARG CONTAINER_GROUP
ARG CONTAINER_GID

RUN addgroup -g $CONTAINER_GID $CONTAINER_GROUP && \
    adduser -D -H -G $CONTAINER_GROUP -u $CONTAINER_UID $CONTAINER_USER && \
    chown -R $CONTAINER_USER:$CONTAINER_GROUP /home/flask

USER $CONTAINER_USER

Запуск контейнера

Опять же, это требует, чтобы вы были корнем:

docker-compose -f docker-compose_base_1.283_production.yml -f docker-compose_production.yml up -d

В результате

Creating network "docker_default" with the default driver
Creating peterspython_container_web ... done

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

docker ps

который возвращается:

CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                    NAMES
292aa9bcecaf        peterspython_image_web:1.283   "/usr/local/bin/guni…"   18 hours ago        Up 18 hours         0.0.0.0:8000->8000/tcp   peterspython_container_web

Затем войдите в работающий контейнер:

docker exec -it 292aa9bcecaf sh

Обратите внимание, что мы начинаем с sh, а не с bash, потому что bash нет в Alpine изображении.

Резюме

Это не так уж сложно, когда вы понимаете (часть) Docker и (часть) ISPConfig. Теперь вы можете запускать все, что угодно на ISPConfig сервере.

Я использовал максимум ISPConfig услуг, я счастлив, MariaDB но некоторые люди могут жаловаться, что, например, PostgreSQL не поддерживается. Было бы неплохо добавить PostgreSQL в качестве опции. ISPConfig Это было бы лучше, чем добавить услугу PostgreSQL к контейнеру, увеличив его размер.

Проблема в том, что при загрузке контейнера Docker image , запуске и остановке контейнера мы должны быть суперпользователями, т.е. для каждой Docker команды это требуется, поэтому данный метод не подходит только для некоторых случайных клиентов. Было бы неплохо, если бы поддерживался метод разрешения для каждого сайта и Docker-Compose команд. В контейнерах также находятся порты, которые могут вступать в конфликт с существующими. Это можно решить, назначив диапазон портов для каждого сайта.

Достаточно ли ISPConfig безопасна установка с помощью арестованных учетных данных пользователя Shell для запуска контейнера? Я вижу возможную проблему с использованием UID и запуском корневого контейнера. UID заключенного пользователя Shell User peterpepyco аналогичен UID web73, что означает, что Docker контейнер на самом деле работает как web73:client2, а не как peterpepyco:client2. Я должен разобраться с этим подробнее. Возможно, можно использовать пространство имен. Но на данный момент я счастлив, что он работает.

Ссылки / кредиты

How do I add a user when I'm using Alpine as a base image?
https://stackoverflow.com/questions/49955097/how-do-i-add-a-user-when-im-using-alpine-as-a-base-image

Running Docker Containers as Current Host User
https://jtreminio.com/blog/running-docker-containers-as-current-host-user/

Compose file version 3 reference
https://docs.docker.com/compose/compose-file/

How to copy Docker images from one host to another without using a repository
https://stackoverflow.com/questions/23935141/how-to-copy-docker-images-from-one-host-to-another-without-using-a-repository

Isolate containers with a user namespace
https://docs.docker.com/engine/security/userns-remap/

Оставить комментарий

Комментируйте анонимно или войдите в систему, чтобы прокомментировать.

Комментарии

Оставьте ответ

Ответьте анонимно или войдите в систему, чтобы ответить.