diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..9cc1216d8adb604d33db6ea92ba9d32ef3db9131
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,215 @@
+# Created by https://www.gitignore.io/api/venv,django,python,visualstudiocode
+# Edit at https://www.gitignore.io/?templates=venv,django,python,visualstudiocode
+
+### Django ###
+*.log
+*.pot
+*.pyc
+__pycache__/
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+media
+*/__pycache__/*
+/static/
+media/
+.coverage
+virtualenv
+
+# If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/
+# in your Git repository. Update and uncomment the following line accordingly.
+# <django-project-name>/staticfiles/
+
+### Django.Python Stack ###
+# Byte-compiled / optimized / DLL files
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+.pip_cache
+pylint
+coverage.svg
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# pyenv
+.python-version
+
+# pipenv
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+#   However, in case of collaboration, if having platform-specific dependencies or dependencies
+#   having no cross-platform support, pipenv may install dependencies that don't work, or not
+#   install all needed dependencies.
+#Pipfile.lock
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# Mr Developer
+.mr.developer.cfg
+.project
+.pydevproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+### Python ###
+# Byte-compiled / optimized / DLL files
+
+# C extensions
+
+# Distribution / packaging
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+
+# Installer logs
+
+# Unit test / coverage reports
+
+# Translations
+
+# Scrapy stuff:
+
+# Sphinx documentation
+
+# PyBuilder
+
+# pyenv
+
+# pipenv
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+#   However, in case of collaboration, if having platform-specific dependencies or dependencies
+#   having no cross-platform support, pipenv may install dependencies that don't work, or not
+#   install all needed dependencies.
+
+# celery beat schedule file
+
+# SageMath parsed files
+
+# Spyder project settings
+
+# Rope project settings
+
+# Mr Developer
+
+# mkdocs documentation
+
+# mypy
+
+# Pyre type checker
+
+### venv ###
+# Virtualenv
+# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
+pyvenv.cfg
+# .env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+pip-selfcheck.json
+
+### VisualStudioCode ###
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+.vscode/
+
+### VisualStudioCode Patch ###
+# Ignore all local history of files
+.history
+
+# End of https://www.gitignore.io/api/venv,django,python,visualstudiocode
+
+#misc
+__pycache__/
+db.sqlite3
+.coverage
+htmlcov/
+flowchart/
+client_secrets.json
+
+# Pycharm IDE
+.idea
+
+# MacOS
+.DS_Store
diff --git a/.gitignore b/.gitignore
index 7e6811adf6066c047eb2fca79f1f49238d300bc2..201fff45d293a39d267948d4138e4dab76dac7f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -179,6 +179,7 @@ dmypy.json
 # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
 pyvenv.cfg
 .env
+.env.db
 .venv
 env/
 venv/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a94fc4b6167280350f0eb8572ee77136b3ebbe65..56c0fe222c91070572fc79fbe4a6e8afe6d12ea4 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -4,10 +4,8 @@ stages:
   - deploy
 
 pylint:
-  image: python:3.7
+  image: farhanazmi/digipus-base
   stage: test
-  before_script:
-    - pip install -r requirements.txt
   script:
     - mkdir ./pylint
     - git ls-files | grep -v 'migrations' | grep -v 'settings.py' | grep -v 'manage.py' | grep -E '.py$' | xargs pylint -E --load-plugins=pylint_django --output-format=text --score=yes | tee ./pylint/pylint.log || pylint-exit $?
@@ -25,12 +23,11 @@ UnitTest:
     POSTGRES_DB: gitlab_test
     POSTGRES_USER: gitlab_test
     POSTGRES_PASSWORD: SebuahPassword
-  image: python:3.7
+  image: farhanazmi/digipus-base
   stage: test
   coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+)%/'
   before_script:
     - export DATABASE_URL=postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres:5432/$POSTGRES_DB
-    - pip install -r requirements.txt
     - python manage.py makemigrations
     - python manage.py migrate
     - python manage.py collectstatic --no-input
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..63ec64d5417c3e4926d7c66b83da3447bd553b5f
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,41 @@
+# BUILDER
+
+FROM python:3.7-slim as builder
+
+RUN apt-get update \
+    && apt-get -y upgrade \
+    && apt-get -y install --no-install-recommends gcc python3-dev libpq-dev \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists/*
+
+WORKDIR /usr/src/app
+
+ENV PYTHONDONTWRITEBYTECODE 1
+ENV PYTHONUNBUFFERED 1
+
+COPY . .
+RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt
+
+# FINAL
+
+FROM python:3.7-slim
+
+RUN apt-get update \
+    && apt-get -y upgrade \
+    && apt-get -y install --no-install-recommends gcc python3-dev libpq-dev
+
+RUN mkdir -p /home/digipus
+ENV APP_HOME=/home/digipus/
+RUN mkdir $APP_HOME/staticfiles
+RUN mkdir $APP_HOME/mediafiles
+WORKDIR $APP_HOME
+
+COPY . .
+
+COPY --from=builder /usr/src/app/wheels /wheels
+COPY --from=builder /usr/src/app/requirements.txt .
+RUN pip install --no-cache /wheels/*
+
+EXPOSE 8000
+VOLUME ["/home/digipus/staticfiles", "/home/digipus/mediafiles"]
+CMD ["gunicorn", "--bind", "0.0.0.0:8000", "digipus.wsgi:application", "--reload"]
diff --git a/Dockerfile.base b/Dockerfile.base
new file mode 100644
index 0000000000000000000000000000000000000000..b00e204e9ba0a2683d17aeca044ea9c07e78bf78
--- /dev/null
+++ b/Dockerfile.base
@@ -0,0 +1,17 @@
+FROM python:3.7-slim
+
+RUN apt-get update \
+    && apt-get -y upgrade \
+    && apt-get -y install --no-install-recommends gcc python3-dev libpq-dev git-all \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists/*
+
+WORKDIR /usr/src/app
+
+ENV PYTHONDONTWRITEBYTECODE 1
+ENV PYTHONUNBUFFERED 1
+
+COPY requirements.txt .
+RUN pip install -r requirements.txt
+
+CMD [ "python" ]
\ No newline at end of file
diff --git a/README.md b/README.md
index e336770c806ff24c07785ee3f7eb0862211c1b5f..3f9309c91fb5dc38b86149b9f6f7161f35dbfde4 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@
 - [Description](#description) 
 - [Initial Setup](#initial-setup)
 - [Running Development Environment](#running-development-environment)
+- [Running Development Environment with Docker Compose](#running-development-environment-with-docker-compose)
 - [Contributors](#contributors)
 
 ## Description
@@ -114,6 +115,62 @@ You can load an some initial data with this command:
 python3 manage.py loaddata */fixtures/initial.json 
 ```
 
+## Running Development Environment with Docker Compose
+Requires [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/).
+
+If you have already created a `.env` file, adjust its content to:
+```bash
+SECRET_KEY=place-your-secret-key-here
+IS_LOCAL=True
+DB_NAME=marjinal
+DB_USER=postgres
+DB_PASSWORD=postgres
+DB_HOST=db
+DB_PORT=5432
+```
+
+Create a `.env.db` file, fill its content with:
+```bash
+POSTGRES_USER=postgres
+POSTGRES_PASSWORD=postgres
+POSTGRES_DB=marjinal
+```
+
+To build and run the containers:
+```bash
+docker-compose up -d --build
+```
+
+To run the containers without rebuilding them first:
+```bash
+docker-compose up -d
+```
+
+To stop the containers:
+```bash
+docker-compose down
+```
+
+To run any command related to the DIGIPUS container:
+```bash
+docker-compose exec digipus <command>
+```
+
+For example, to migrate the database:
+```bash
+docker-compose exec digipus python manage.py migrate
+```
+
+To run any command related to the database container:
+```bash
+docker-compose exec db <command>
+```
+
+For example, to run `psql`:
+```bash
+docker-compose exec db psql -U postgres
+```
+
 ## Contributors
 This repository is one of the projects from the Software Project course.
 
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a595488cc40c670433ef120484d40fb3b8627b70
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,24 @@
+version: "3.7"
+
+services:
+  digipus:
+    build: .
+    env_file:
+      - .env
+    ports:
+    - 8000:8000
+    depends_on:
+      - db
+  db:
+    image: postgres:12
+    volumes:
+    - postgres_data:/var/lib/postgresql/data/
+    - static_volume:/home/digipus/staticfiles
+    - media_volume:/home/digipus/mediafiles
+    env_file:
+      - .env.db
+
+volumes:
+  postgres_data:
+  static_volume:
+  media_volume: