-
Notifications
You must be signed in to change notification settings - Fork 58
Dockerizing Applications and PR CI CD Setup
This documentation provides a comprehensive guide for Dockerizing applications and configuring CI/CD pipelines using GitHub Actions. It covers the steps for containerizing backend and frontend applications, setting up environment-specific Docker Compose files, and automating deployments with GitHub Actions.
To containerize your backend and frontend applications and set up Docker Compose for seamless development and deployment.
- Backend Dockerfile: Define the environment and instructions for building the backend container.
- Frontend Dockerfile: Define the environment and instructions for building the frontend container.
FROM php:8.2-fpm
RUN apt-get update && apt-get install -y \
libpng-dev \
libjpeg-dev \
libfreetype6-dev \
libzip-dev \
libpq-dev \
git \
unzip \
&& rm -rf /var/lib/apt/lists/*
RUN pecl install apcu \
&& docker-php-ext-enable apcu
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install gd zip pdo pdo_pgsql
COPY php.ini /usr/local/etc/php/conf.d/custom.ini
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
COPY . /var/www/html
RUN composer install --no-interaction --prefer-dist --optimize-autoloader
RUN cp .env.example .env
RUN echo "apc.enable_cli=1" >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini
CMD ["sh", "-c", "nohup php artisan serve --host=0.0.0.0 "]
FROM node:20-alpine AS base
WORKDIR /app
COPY . .
RUN npm install -g pnpm
RUN pnpm install
RUN pnpm run build
EXPOSE 3000
CMD ["node", "server.js"]
Define a docker-compose.yml file at the root of your project to orchestrate services including backend, frontend, databases, proxy, and Redis.
services:
app:
build:
context: .
ports:
- "8000:8000"
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
environment:
- APP_ENV=production
- APP_DEBUG=false
- DB_CONNECTION=pgsql
- DB_HOST=db
- DB_PORT=5432
- DB_DATABASE=app
- DB_USERNAME=app
- DB_PASSWORD=changethis123
- QUEUE_CONNECTION=redis
- REDIS_HOST=redis
- REDIS_PORT=6379
db:
image: postgres:latest
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: changethis123
POSTGRES_DB: app
ports:
- "5432:5432"
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 10s
retries: 5
start_period: 30s
timeout: 5s
proxy:
image: 'jc21/nginx-proxy-manager:latest'
restart: always
ports:
- '8090:81'
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- ./certs:/etc/nginx/letsencrypt
- /var/run/docker.sock:/tmp/docker.sock:ro
redis:
image: redis:latest
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
retries: 3
start_period: 30s
timeout: 5s
redis-commander:
image: rediscommander/redis-commander:latest
ports:
- "8081:8081"
environment:
- REDIS_HOSTS=local:redis:6379
adminer:
image: adminer:latest
ports:
- "8080:8080"
environment:
ADMINER_DEFAULT_SEVERAL: db
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./fastcgi-php.conf:/etc/nginx/snippets/fastcgi-php.conf
depends_on:
- "app"
volumes:
db_data:
Ensure services communicate properly with each other.
These will manage different configurations for staging and production environments by using environment-specific Docker Compose files.
-
Create docker-compose.staging.yml Configure services and settings tailored for the staging environment.
-
Create docker-compose.production.yml Configure services and settings tailored for the production environment.
###Docker-compose.staging.yml:
version: '3.8'
services:
app-delve:
image: delve_be:latest
ports:
- "8000:8000"
depends_on:
db-delve:
condition: service_healthy
redis-delve:
condition: service_healthy
environment:
- APP_ENV=staging
- APP_DEBUG=true
- DB_CONNECTION=pgsql
- DB_HOST=db
- DB_PORT=5432
- DB_DATABASE=app_staging
- DB_USERNAME=app_staging
- DB_PASSWORD=changethis123
- QUEUE_CONNECTION=redis
- REDIS_HOST=redis
- REDIS_PORT=6379
- WWWGROUP=1000
- WWWUSER=1000
db-delve:
image: postgres:latest
environment:
POSTGRES_USER: app_staging
POSTGRES_PASSWORD: changethis123
POSTGRES_DB: app_staging
ports:
- "5400:5432"
volumes:
- db-delve_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app_staging"]
interval: 10s
retries: 5
start_period: 30s
timeout: 5s
redis-delve:
image: redis:latest
ports:
- "6374:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
retries: 3
start_period: 30s
timeout: 5s
adminer:
image: adminer:latest
ports:
- "8080:8080"
environment:
ADMINER_DEFAULT_SEVERAL: db
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./fastcgi-php.conf:/etc/nginx/snippets/fastcgi-php.conf
depends_on:
- "app"
proxy:
image: 'jc21/nginx-proxy-manager:latest'
restart: always
ports:
- '8090:81'
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- ./certs:/etc/nginx/letsencrypt
- /var/run/docker.sock:/tmp/docker.sock:ro
volumes:
db-delve_data:
version: '3.8'
services:
app:
build:
context: .
ports:
- "8000:8000"
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
environment:
- APP_ENV=production
- APP_DEBUG=false
- DB_CONNECTION=pgsql
- DB_HOST=db
- DB_PORT=5432
- DB_DATABASE=app
- DB_USERNAME=app
- DB_PASSWORD=changethis123
- QUEUE_CONNECTION=redis
- REDIS_HOST=redis
- REDIS_PORT=6379
db:
image: postgres:latest
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: changethis123
POSTGRES_DB: app
ports:
- "5432:5432"
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 10s
retries: 5
start_period: 30s
timeout: 5s
proxy:
image: 'jc21/nginx-proxy-manager:latest'
restart: always
ports:
- '8090:81'
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- ./certs:/etc/nginx/letsencrypt
- /var/run/docker.sock:/tmp/docker.sock:ro
redis:
image: redis:latest
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
retries: 3
start_period: 30s
timeout: 5s
redis-commander:
image: rediscommander/redis-commander:latest
ports:
- "8081:8081"
environment:
- REDIS_HOSTS=local:redis:6379
adminer:
image: adminer:latest
ports:
- "8080:8080"
environment:
ADMINER_DEFAULT_SEVERAL: db
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./fastcgi-php.conf:/etc/nginx/snippets/fastcgi-php.conf
depends_on:
- "app"
volumes:
db_data:
Automate Pull Request deployment using GitHub Actions and Docker. Use HNG project's pr-deploy GitHub Action:
Follow instructions from the https://github.com/hngprojects/pr-deploy
to set up pull request deployments.
Ensure the action is configured to deploy previews for pull requests. In your GitHub Actions workflow, build Docker images for your application.
This workflow below will deploy on push or pull request.
- On push, it will build the image, Use
scp
to upload the built images to the server, thendocker load
the image and run it using the appropriatedocker-compose file
.
name: PR and DevOps Deploy
on:
pull_request:
types: [opened, synchronize, reopened, closed]
push:
branches:
- devops
jobs:
build_and_deploy:
if: github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Build Docker Image
run: |
IMAGE_TAG="latest"
docker buildx build --tag delve_be:${IMAGE_TAG} --file Dockerfile .
- name: List Docker Images
run: docker images
- name: Save Docker Image
run: |
IMAGE_TAG="latest"
docker save delve_be:${IMAGE_TAG} -o delve_be.tar
- name: Upload Docker Image Artifact
uses: actions/upload-artifact@v2
with:
name: docker-image
path: delve_be.tar
deploy_to_server:
if: github.event_name == 'push'
needs: build_and_deploy
runs-on: ubuntu-latest
steps:
- name: Download Docker Image Artifact
uses: actions/download-artifact@v2
with:
name: docker-image
path: .
- name: Transfer Docker Image to Server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
source: delve_be.tar
target: /tmp/php
- name: Load and Deploy Docker Image on Server
uses: appleboy/[email protected]
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
script: |
IMAGE_TAG="latest"
cd /tmp/php
docker load < delve_be.tar
rm -f delve_be-${IMAGE_TAG}.tar
cd /var/www/langlearnai-be/pr
git pull origin devops
docker-compose -f docker-compose.staging.yml down
docker-compose -f docker-compose.staging.yml up -d
deploy-pr:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- id: deploy
name: Pull Request Deploy
uses: hngprojects/pr-deploy@dev
with:
server_host: ${{ secrets.SSH_HOST }}
server_username: ${{ secrets.SSH_USER }}
server_password: ${{ secrets.SSH_PASSWORD }}
comment: true
context: '.'
dockerfile: 'Dockerfile'
exposed_port: '7001'
github_token: ${{ secrets.TOKEN }}
- name: Print Preview Url
run: |
echo "Preview Url: ${{ steps.deploy.outputs.preview-url }}"
By following these steps, you will be able to Dockerize your applications and managing deployments across different environments using GitHub Actions.
Made with ❤️ by Olat-nji | Ujusophy | tulbadex | Darkk-kami | Otie16 courtesy of @HNG-Internship