diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000000000000000000000000000000000000..b3d3d5b13094cd95c19aa5a3e44b99841759524b
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,8 @@
+POSTGRES_USER=
+POSTGRES_PASSWORD=
+POSTGRES_DB=
+POSTGRES_HOST=
+POSTGRES_PORT=
+JWT_SECRET =
+BASIC_AUTH_USERNAME =
+BASIC_AUTH_PASSWORD =
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 058a472a5b08098ef2f3ba961a76f900f3b73c7a..34fee1079a68451cc8dd7d4ed2487263088d6d0b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 .env
 /tmp
-/db-data
\ No newline at end of file
+/db-data
+/.vscode
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..320b787220be27623b60bb39da7276847fb7333d
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,61 @@
+stages:          # List of stages for jobs, and their order of execution
+  - test
+  - build
+  - deploy
+
+test-job:
+  stage: test
+  rules:
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event' && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'staging' || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'production') 
+  script:
+    - echo 'Testing'
+
+build-job:       # This job runs in the build stage, which runs first.
+  stage: build
+  image: docker:latest
+  when: on_success
+  variables:
+    DOCKER_DRIVER: overlay2
+    DOCKER_TLS_CERTDIR: ""
+  services:
+    - name: 'docker:dind'
+  rules:
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'production'
+  before_script:
+    - apk add --no-cache curl jq python3 py3-pip
+    - python3 -m venv awscli-env
+    - source awscli-env/bin/activate
+    - pip install awscli
+    - aws ecr get-login-password --region ap-southeast-2 | docker login --username AWS --password-stdin $DOCKER_REGISTRY
+    - aws --version
+    - docker info
+    - docker --version
+    - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER $CI_REGISTRY --password-stdin
+  script:
+    - docker build -t graduit-be .
+    - docker tag graduit-be:latest $DOCKER_REGISTRY/graduit-be:latest
+    - docker push $DOCKER_REGISTRY/graduit-be:latest
+
+deploy-job:
+  stage: deploy
+  image: docker:latest
+  when: on_success
+  variables:
+    DOCKER_DRIVER: overlay2
+    DOCKER_TLS_CERTDIR: ""
+  services:
+    - name: 'docker:dind'
+  rules:
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'production'
+  before_script:
+    - apk add --no-cache curl jq python3 py3-pip
+    - python3 -m venv awscli-env
+    - source awscli-env/bin/activate
+    - pip install awscli
+    - aws ecr get-login-password --region ap-southeast-2 | docker login --username AWS --password-stdin $DOCKER_REGISTRY
+    - aws --version
+    - docker info
+    - docker --version
+    - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER $CI_REGISTRY --password-stdin
+  script:
+    - echo 'Building...'
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index d3309c40ea810f11c2f9a9f9b76ac9fa67eeb613..5290a0b3b0615b692d2375a6dd1cb48521735e53 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -8,4 +8,5 @@ RUN go install github.com/cosmtrek/air@latest
 COPY . .
 RUN go mod tidy
 
+EXPOSE 8080
 CMD ["air", "./src/cmd/rest.go", "-b", "0.0.0.0"]
\ No newline at end of file
diff --git a/docker-compose.prod.yaml b/docker-compose.prod.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ed850228ba67b41d3b9eaeb75d51cb0a93f392fc
--- /dev/null
+++ b/docker-compose.prod.yaml
@@ -0,0 +1,26 @@
+version: "3.8"
+services:
+  graduit_server:
+    build: .
+    ports:
+      - 8080:8080
+    hostname: graduit_server
+    env_file: .env
+    volumes:
+      - ./:/usr/app
+      - /usr/app/db-data
+    restart: always
+    depends_on:
+      - graduit_db
+  graduit_db:
+    image: public.ecr.aws/docker/library/postgres:latest
+    ports:
+      - ${POSTGRES_PORT}:5432
+    hostname: graduit_db
+    env_file: .env
+    volumes:
+      - ./db-data:/var/lib/postgresql/data
+    environment:
+      POSTGRES_USER: ${POSTGRES_USER}
+      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
+      POSTGRES_DB: ${POSTGRES_DB}
diff --git a/script/run.sh b/script/run.sh
new file mode 100644
index 0000000000000000000000000000000000000000..fd14bd297156a71a0a50ce64b91f7da38e9c1cae
--- /dev/null
+++ b/script/run.sh
@@ -0,0 +1,2 @@
+// seed database
+go run ./seeder/status_ta.go
\ No newline at end of file
diff --git a/src/database/Database.go b/src/database/Database.go
index 0e3af6b1ad4ad6253fe04fa65cd6907e2deaee48..f2ffbc2b160a5932900dacda4e3b9348cda79413 100644
--- a/src/database/Database.go
+++ b/src/database/Database.go
@@ -21,6 +21,7 @@ func initialize() {
 	name := os.Getenv("POSTGRES_DB")
 	port := os.Getenv("POSTGRES_PORT")
 
+	print(host)
 	dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable", host, user, pass, name, port)
 	print(dsn)