4

I am attempting to build a simple app with FastAPI and React. I have been advised by our engineering dept, that I should Dockerize it as one app instead of a front and back end...

I have the app functioning as I need without any issues, my current directory structure is.

.
├── README.md
├── backend
│   ├── Dockerfile
│   ├── Pipfile
│   ├── Pipfile.lock
│   └── main.py
└── frontend
    ├── Dockerfile
    ├── index.html
    ├── package-lock.json
    ├── package.json
    ├── postcss.config.js
    ├── src
    │   ├── App.jsx
    │   ├── favicon.svg
    │   ├── index.css
    │   ├── logo.svg
    │   └── main.jsx
    ├── tailwind.config.js
    └── vite.config.js

I am a bit of a Docker noob and have only ever built an image for projects that don't arent split into a front and back end.

I have a .env file in each, only simple things like URLs or hosts.

I currently run the app, with the front end and backend separately as an example.

> ./frontend
> npm run dev
> ./backend
> uvicorn .... 

Can anyone give me tips /advice on how I can dockerize this as one?

0

2 Answers 2

5

As a good practice, one docker image should contain one process. Therefore you should dockerize them separatly (have one Dockerfile per app).

Then, you can add a docker-compose.yml file at the root of your project in order to link them together, it could look like that:

version: '3.3'

services:
  app:
    build:
      context: ./frontend/
      dockerfile: ./Dockerfile
    ports:
      - "127.0.0.1:80:80"

  backend:
    env_file:
      - backend/.env
    build:
      context: ./backend/
      dockerfile: ./Dockerfile
    ports:
      - "127.0.0.1:8000:80"

The backend would be running on http://localhost:8000 and the frontend on http://localhost:80

In order to start the docker-compose you can just type in your shell:

$> docker-compose up

This implies that you already have your Dockerfile for both apps. You can find many example online of different implementations of Dockerfile for the different technologies. For example :

  • For ReactJS you can configure it like this
  • For FastAPI Like that
0
3

Following up on Vinalti's answer. I would also recommend using one Dockerfile for the backend, one for the frontend and a docker-compose.yml file to link them together. Given the following project structure, this is what worked for me.

Project running fastapi (backend) on port 8000 and reactjs (frontend) on port 3006.

.
├── README.md
├── docker-compose.yml
├── backend
│   ├── .env
│   ├── Dockerfile
│   ├── app/
│   ├── venv/
│   ├── requirements.txt
│   └── main.py
└── frontend
    ├── .env
    ├── Dockerfile
    ├── package.json
    ├── package-lock.json
    ├── src/
    ├── ...

backend/Dockerfile

FROM python:3.10
WORKDIR /code
COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./ /code/
CMD ["uvicorn", "app.api:app", "--host", "0.0.0.0", "--port", "8000"]

frontend/Dockerfile

# pull official base image
FROM node:latest as build
# set working directory
WORKDIR /app
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
# install app dependencies
COPY package.json ./
COPY package-lock.json ./
# Silent clean install of npm
RUN npm ci --silent
RUN npm install [email protected] -g --silent
# add app
COPY . /app/

# Build production
RUN npm run build
RUN npm install -g serve

## Start the app on port 3006
CMD serve -s build -l 3006

docker-compose.yml

version: '3.8'
services:
  backend:
    env_file:
      - backend/.env
    build:
      context: ./backend/
      dockerfile: ./Dockerfile
    restart: always
    ports:
      - "127.0.0.1:8000:8000"
    expose:
      - 8000

  frontend:
    env_file:
      - frontend/.env
    build:
      context: ./frontend/
      dockerfile: ./Dockerfile
    restart: always
    ports:
      - "127.0.0.1:3006:3006"
    expose:
      - 3006

Not the answer you're looking for? Browse other questions tagged or ask your own question.