Environment: Ubuntu 23.10
Docker Version: 26.1.2
Docker Compose Ver: 2.27
1. Dockerfile for Nextjs front end placed parallel to package.json file
FROM node:20.12.2-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]
1.a. .env
NEXT_PUBLIC_BASE_URL=http://192.168.x.x:8000
2. Dockerfile for Python backend placed above src folder
FROM python:3.11.4-alpine3.18
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /usr/src/app
COPY ./src/requirements/requirements_dev.txt /usr/src/app
COPY ./src/requirements/base.txt /usr/src/app
RUN pip install --upgrade pip && \
apk update && \
apk add postgresql-dev gcc python3-dev musl-dev jpeg-dev zlib-dev curl && \
pip install -r requirements_dev.txt
COPY ./src/.env /usr/src/app
RUN mkdir /usr/src/app/logs
COPY ./entrypoint.sh /usr/src/app
RUN sed -i 's/\r$//g' ./entrypoint.sh
RUN chmod 777 ./entrypoint.sh
COPY ./src /usr/src/app/
RUN chmod 777 ./es_index.py
ENTRYPOINT ["./entrypoint.sh"]
2.a. entrypoint.sh
#!/bin/sh
export POSTGRES_HOST="db"
if [ $DATABASE = "postgres" ]
then
echo "Waiting for postgres to load..."
while ! nc -z $POSTGRES_HOST $POSTGRES_PORT; do
sleep 0.1
done
echo "postgres ready to run"
python manage.py makemigrations
python manage.py migrate --no-input
fi
python manage.py createsuperuser --noinput --username $DJANGO_SUPERUSER_USERNAME --email $DJANGO_SUPERUSER_EMAIL
python es_index.py
exec "$@"
2.b. vi .env
# secret key
SECRET_KEY=ac6cd19772005f224cefb220060037bf15f35a6e3e1826a1095a26fc
# database stuffs
DATABASE=postgres
DB_ENGINE=django.db.backends.postgresql
POSTGRES_DB=courses
POSTGRES_USER=postgres
POSTGRES_PASSWORD=xxxxx
POSTGRES_PORT=5432
POSTGRES_HOST=db
# superuser setup
DJANGO_SUPERUSER_USERNAME=admin
DJANGO_SUPERUSER_PASSWORD=admin
DJANGO_SUPERUSER_EMAIL=admin@gmail.com
# smtp setup
EMAIL_HOST_USER=courses@xxxxxx.org
EMAIL_HOST_PASSWORD=titygjzkngqtzoek
# celery stuffs
#CELERY_BROKER_URL=amqp://guest:guest@localhost:15672/
#CELERY_RESULT_BACKEND=db+postgresql://postgres:admin@localhost:5432/celery_tasks
# Adjust for dockerizatin
CELERY_BROKER_URL=amqp://myuser:mypassword@rabbitmq:5672
CELERY_RESULT_BACKEND=db+postgresql://postgres:admin@db:5432/celery_tasks
ADMIN_USER=xxxxxx@xxxxxx.org
# elastic
#ES_HOST=localhost
ES_HOST=elasticsearch
ES_NUMBER_OF_SHARDS=1
ES_NUMBER_OF_REPLICAS=0
ES_USE_SSL=False
ES_PORT=9200
ES_INDEX=seepalaya
3. Dockerfile for Celery
FROM python:3.11.4-alpine3.18
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /usr/src/app
COPY ./src/requirements/requirements_dev.txt /usr/src/app
COPY ./src/requirements/base.txt /usr/src/app
RUN pip install --upgrade pip && \
apk update && \
apk add postgresql-dev gcc python3-dev musl-dev jpeg-dev zlib-dev && \
pip install -r requirements_dev.txt
COPY ./src/.env /usr/src/app
RUN mkdir /usr/src/app/logs
COPY ./src /usr/src/app/
3.a .env
similar to above
4. Dockerfile for Postgres
FROM postgres:15.7-alpine3.18
ENV PG_MAX_WAL_SENDERS 8
ENV PG_WAL_KEEP_SEGMENTS 8
#Set timezone
ENV TZ=Asia/Kathmandu
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# Copy the custom initialization script to the Docker image
COPY create_celery.sh /docker-entrypoint-initdb.d/
COPY *.sql /tmp/
COPY populate_ep.sh /docker-entrypoint-initdb.d/
# Grant execution permissions to the script
RUN chmod +x /docker-entrypoint-initdb.d/create_celery.sh
RUN chmod +x /docker-entrypoint-initdb.d/populate_ep.sh
4a. create_celery.sh
#!/bin/bash
set -e
# Create additional databases
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
CREATE DATABASE celery_tasks;
EOSQL
4b. populate_ep.sh
#!/bin/bash
set -e
# Function to check if the database exists
db_exists() {
psql -U "$POSTGRES_USER" -tc "SELECT 1 FROM pg_database WHERE datname = 'pustakalaya'" | grep -q 1
}
# Create the database if it does not exist
if ! db_exists; then
psql -U "$POSTGRES_USER" -c "CREATE DATABASE pustakalaya"
fi
# Create the user and grant privileges
psql -U "$POSTGRES_USER" <<-EOSQL
DO \$\$
BEGIN
IF NOT EXISTS (SELECT FROM pg_catalog.pg_user WHERE usename = 'pustakalaya_user') THEN
CREATE USER pustakalaya_user WITH PASSWORD 'pustakalaya123';
END IF;
END
\$\$;
GRANT ALL PRIVILEGES ON DATABASE pustakalaya TO pustakalaya_user;
EOSQL
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname=pustakalaya < /tmp/pustakalaya.sql
4.c. .env
POSTGRES_DB=courses
POSTGRES_USER=postgres
POSTGRES_PASSWORD=xxxxx
5. docker-compose.yml
version: "3.8"
services:
db:
build:
context: seepalaya-new-database
dockerfile: Dockerfile.postgres
container_name: seepalaya-db
env_file:
- ./seepalaya-new-database/.env
volumes:
- ./db/:/var/lib/postgresql/
networks:
- seepalaya-new
restart: always
seepalaya-backend:
build:
context: seepalaya-new-backend
dockerfile: Dockerfile
container_name: seepalaya-backend
command: "python manage.py runserver 0.0.0.0:8000"
ports:
- 8000:8000
env_file:
- ./seepalaya-new-backend/src/.env
environment:
- CELERY_BROKER_URL=amqp://myuser:mypassword@rabbitmq:5672
depends_on:
- db
networks:
- seepalaya-new
restart: always
rabbitmq:
image: rabbitmq:3-management
ports:
- "5672:5672"
environment:
- RABBITMQ_DEFAULT_USER=myuser
- RABBITMQ_DEFAULT_PASS=mypassword
networks:
- seepalaya-new
restart: always
seepalaya-celery:
build:
context: seepalaya-new-celery
dockerfile: Dockerfile
container_name: seepalaya-celery
command: celery -A config worker -l info
environment:
- CELERY_BROKER_URL=amqp://myuser:mypassword@rabbitmq:5672
depends_on:
- rabbitmq
- seepalaya-backend
networks:
- seepalaya-new
restart: always
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
environment:
- discovery.type=single-node
ports:
- "9200:9200"
networks:
- seepalaya-new
restart: always
seepalaya-front:
build:
context: seepalaya_new
dockerfile: Dockerfile
container_name: seepalaya-front
env_file:
- ./seepalaya_new/.env
ports:
- "3000:3000"
networks:
- seepalaya-new
restart: always
networks:
seepalaya-new:
driver: bridge