0

I am creating a web application with FastApi using docker. I have two containers: one for the application and another for the database, this is the docker compose:

version: '3.8'

services:
  web:
    build:
      context: .
      dockerfile: ./compose/local/Dockerfile
    image: fastapi_example_web
    # '/start' is the shell script used to run the service
    command: /start
    # this volume is used to map the files and folders on the host to the container
    # so if we change code on the host, code in the docker container will also be changed
    volumes:
      - .:/app
    ports:
      - 8020:8000
    env_file:
      - .env/.dev
    depends_on:
      - db

  db:
    build:
      context: ./compose/local/postgres
      dockerfile: Dockerfile
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    expose:
      - 5432:5432
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres

This is the DockerFile and scripts for the web container:

FROM python:3.10-slim-buster

ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1

RUN apt-get update \
  # dependencies for building Python packages
  && apt-get install -y build-essential \
  # psycopg2 dependencies
  && apt-get install -y libpq-dev \
  # Additional dependencies
  && apt-get install -y telnet netcat \
  # cleaning up unused files
  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
  && rm -rf /var/lib/apt/lists/*

# Requirements are installed here to ensure they will be cached.
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt

COPY ./compose/local/entrypoint /entrypoint
RUN sed -i 's/\r$//g' /entrypoint
RUN chmod +x /entrypoint

COPY ./compose/local/start /start
RUN sed -i 's/\r$//g' /start
RUN chmod +x /start


WORKDIR /app

ENTRYPOINT ["/entrypoint"]

entrypoint:

#!/bin/bash

echo "Waiting for postgres..."

while ! nc -z db 5432; do
  sleep 0.1
done

echo "PostgreSQL started"

exec "$@"

start:

#!/bin/bash

set -o errexit
set -o pipefail
set -o nounset

uvicorn app.main:app --reload --reload-dir app --host 0.0.0.0

This is the DockerFile and scripts for the db container:

# pull official base image
FROM postgres:14-alpine

# run create.sql on init
ADD create.sql /docker-entrypoint-initdb.d

create.sql

CREATE DATABASE web_dev;
CREATE DATABASE web_test;

In my application, creating users is a protected endpoint, so I want the first user to be created when the containers are built, inserting it into the database. The problem is that first the "db" container starts (at this moment the tables do not yet exist in the database), then the "web" container starts (at this moment the migrations are applied automatically and the tables are created). In which container and in which part should I create the sql record?

Diegol
  • 87
  • 7
  • It seems like there's a very clear point in the startup sequence of the `web` container where you know that `PostgreSQL started` but you haven't yet started running the Python application; could you load the seed data there? – David Maze Feb 09 '23 at 17:04
  • I need the application to start so that the database tables are generated. You mean after starting the application from the web container add the data (using something like psycopg2?). I wanted to do it from the "db" container but I don't know how to do it: 1. start the "db" container and the databases are created. 2. start the "web" container, start the application and create the tables 3. make the query from the db container to create the record. – Diegol Feb 09 '23 at 19:35
  • Either in the `start` script or immediately after you `echo "PostgreSQL started"` seem like good places to do this. You should have the same connection information and credentials that the main application has, and maybe just run `./manage.py loaddata` ([How to seed Django project ? - insert a bunch of data into the project for initialization](https://stackoverflow.com/questions/51577441/how-to-seed-django-project-insert-a-bunch-of-data-into-the-project-for-initi)). – David Maze Feb 09 '23 at 20:59

0 Answers0