Запустите контейнер докера из существующего контейнера, используя 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 удалить контейнер после завершения его выполнения.