Запустите контейнер докера из существующего контейнера, используя docker-py

У меня есть контейнер Docker, который запускает приложение Flask. Когда Flask получает и http-запрос, я хотел бы запустить новый эфемерный контейнер Docker, который завершает работу, когда завершает свою работу.

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

Каково было бы решение сделать это с помощью docker-py?

2 ответа

Мы делаем такие вещи, монтируя docker.sock в качестве общего тома между хост-машиной и контейнером. Это позволяет контейнеру отправлять команды на компьютер, такие как запуск Docker

это пример из нашей системы CI:

 volumes:
 - /var/run/docker.sock:/var/run/docker.sock

Отвечая на мой собственный вопрос. Вот полная настройка, которая работает. В одной папке создайте следующие файлы:

  • requirements.txt
  • Dockerfile
  • докер-compose.yml
  • api.py

requirements.txt

docker==3.5.0
flask==1.0.2

Dockerfile

FROM python:3.7-alpine3.7


# Project files
ARG PROJECT_DIR=/srv/api
RUN mkdir -p $PROJECT_DIR
WORKDIR $PROJECT_DIR
COPY requirements.txt ./

# Install Python dependencies
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

докер-compose.yml

Обязательно смонтируйте docker.sock в томах, как указано в предыдущем ответе выше.

version: '3'
services:
  api:
    container_name: test
    restart: always
    image: test
    build:
      context: ./
    volumes:
      - ./:/srv/api/
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      FLASK_APP: api.py
    command: ["flask", "run", "--host=0.0.0.0"]
    ports:
      - 5000:5000

api.py

from flask import Flask
import docker
app = Flask(__name__)


@app.route("/")
def hello():
    client = docker.from_env()
    client.containers.run('alpine', 'echo hello world', detach=True, remove=True)
    return "Hello World!"

Затем откройте браузер и перейдите к http://0.0.0.0:5000/

Это вызовет выполнение альпийского контейнера. Если у вас еще нет альпийского изображения, в первый раз это займет немного времени, потому что Docker автоматически загрузит изображение.

Аргументы detach=True позволяет выполнять контейнер асинхронно, так что Flask не ждет окончания процесса перед возвратом своего ответа.

Аргумент remove=True указывает Docker удалить контейнер после завершения его выполнения.

Другие вопросы по тегам