Alexis.Rolland
Alexis.Rolland

Reputation: 6363

Run a docker container from an existing container using docker-py

I have a Docker container which runs a Flask application. When Flask receives and http request, I would like to trigger the execution of a new ephemeral Docker container which shutdowns once it completes what it has to do.

I have read Docker-in-Docker should be avoided so this new container should be run as a sibling container on my host and not within the Flask container.

What would be the solution to do this with docker-py?

Upvotes: 6

Views: 2893

Answers (2)

Alexis.Rolland
Alexis.Rolland

Reputation: 6363

Answering my own question. Here is a complete setup which works. In one folder, create the following files:

  • requirements.txt
  • Dockerfile
  • docker-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

docker-compose.yml

Make sure to mount docker.sock in volumes as mentioned in the previous answer above.

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!"

Then open your browser and navigate to http://0.0.0.0:5000/

It will trigger the execution of the alpine container. If you don't already have the alpine image, it will take a bit of time the first time because Docker will automatically download the image.

The arguments detach=True allows to execute the container asynchronously so that Flask does not wait for the end of the process before returning its response.

The argument remove=True indicates Docker to remove the container once its execution is completed.

Upvotes: 5

gCoh
gCoh

Reputation: 3089

we are doing stuff like this by mounting docker.sock as shared volume between the host machine and the container. This allows the container sending commands to the machine such as docker run

this is an example from our CI system:

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

Upvotes: 10

Related Questions