Configure Docker to host the application
Docker is a popular way to distribute applications. Assuming that you've set all required dependencies in the
setup.py, we're going to create an image with these properties:
- Run by an unprivileged user: Create an unprivileged user with permissions to run our program.
- Robust to vulnerabilities: Don't use Alpine as it's known to react slow to new vulnerabilities. Use a base of Debian instead.
- Smallest possible: Use Docker multi build step. Create a
builderDocker that will run
pip installand copies the required executables to the final image.
FROM python:3.8-slim-buster as base FROM base as builder RUN python -m venv /opt/venv # Make sure we use the virtualenv: ENV PATH="/opt/venv/bin:$PATH" COPY . /app WORKDIR /app RUN pip install . FROM base COPY --from=builder /opt/venv /opt/venv RUN useradd -m myapp WORKDIR /home/myapp # Copy the required directories for your program to work. COPY --from=builder /root/.local/share/myapp /home/myapp/.local/share/myapp COPY --from=builder /app/myapp /home/myapp/myapp RUN chown -R myapp:myapp /home/myapp/.local USER myapp ENV PATH="/opt/venv/bin:$PATH" ENTRYPOINT ["/opt/venv/bin/myapp"]
If we need to use it with MariaDB or with Redis, the easiest way is to use
version: '3.8' services: myapp: image: myapp:latest restart: always links: - db depends_on: - db environment: - AIRSS_DATABASE_URL=mysql+pymysql://myapp:supersecurepassword@db/myapp db: image: mariadb:latest restart: always environment: - MYSQL_USER=myapp - MYSQL_PASSWORD=supersecurepassword - MYSQL_DATABASE=myapp - MYSQL_ALLOW_EMPTY_PASSWORD=yes ports: - 3306:3306 command: - '--character-set-server=utf8mb4' - '--collation-server=utf8mb4_unicode_ci' volumes: - /data/myapp/mariadb:/var/lib/mysql
depends_on flag is not enough to ensure that the database is up when our application tries to connect. So we need to use external programs like wait-for-it. To use it, change the earlier Dockerfile to match these lines:
... FROM base RUN apt-get update && apt-get install -y \ wait-for-it \ && rm -rf /var/lib/apt/lists/* ... ENTRYPOINT ["/home/myapp/entrypoint.sh"]
entrypoint.sh is something like:
#!/bin/bash # Wait for the database to be up if [[ -n $DATABASE_URL ]];then wait-for-it db:3306 fi # Execute database migrations /opt/venv/bin/myapp install # Enter in daemon mode /opt/venv/bin/myapp daemon
Remember to add the permissions to run the script:
chmod +x entrypoint.sh