Create Azure Pipeline for Digital Ocean using Docker and SSH
- Login to Azure DevOps
- Create Azure_Pipeline.yml file for the project
- Add the following code to the file
# Docker
# Build a Docker image
# https://docs.microsoft.com/azure/devops/pipelines/languages/docker
trigger:
- master
resources:
- repo: self
variables:
- group: 'digital-ocean-credentials'
- name: tag
value: $(Build.BuildId)
stages:
- stage: Build
displayName: Build image
jobs:
- job: Build
displayName: Build
pool:
vmImage: ubuntu-latest
steps:
- script: docker compose build
displayName: 'Docker compose build'
- script: |
docker login registry.digitalocean.com -u $(token) -p $(token)
docker tag service-app:latest registry.digitalocean.com/esv-analytics/service-app:$(tag)
docker tag web-app:latest registry.digitalocean.com/esv-analytics/web-app:$(tag)
docker push registry.digitalocean.com/esv-analytics/service-app:$(tag)
docker push registry.digitalocean.com/esv-analytics/web-app:$(tag)
displayName: 'Docker push'
- task: DownloadSecureFile@1
displayName: 'Download DigitalOcean SSH key'
name: sshKey
inputs:
secureFile: 'digital-ocean-ssh-key'
# pull the images from the registry and run them on the DigitalOcean droplet
- script: |
echo "Secure File Path: $(sshKey.secureFilePath)"
chmod 600 $(sshKey.secureFilePath) # Fix permissions
eval $(ssh-agent -s) # Start the SSH agent
mkdir -p ~/.ssh # Ensure the .ssh directory exists
touch ~/.ssh/known_hosts # Ensure the known_hosts file exists
ssh-keyscan -p 18765 $(dropletIP) >> ~/.ssh/known_hosts # Add the remote server to the known hosts file
echo "$(passphrase)" | ssh-add $(sshKey.secureFilePath) # Add the SSH key to the agent
ssh -o StrictHostKeyChecking=no root@$(dropletIP) "docker login registry.digitalocean.com -u $(token) -p $(token)"
ssh -o StrictHostKeyChecking=no root@$(dropletIP) "docker pull registry.digitalocean.com/esv-analytics/service-app:$(tag)"
ssh -o StrictHostKeyChecking=no root@$(dropletIP) "docker pull registry.digitalocean.com/esv-analytics/web-app:$(tag)"
ssh -o StrictHostKeyChecking=no root@$(dropletIP) "cd /root/workspace/esv_matomo_analytics && docker compose down && export IMAGE_TAG=$(tag) && docker compose up -d --build"
displayName: 'Deploy to DigitalOcean'
- Create a new variable group called digital-ocean-credentials
- Add the following variables to the group
token: <Digital Ocean Token>
passphrase: <SSH Key Passphrase>
dropletIP: <Droplet IP Address>
- Create a new secure file called digital-ocean-ssh-key
- Add the SSH key to the file
Create Digital Ocean Droplet
- Login to Digital Ocean
- Create a new droplet
- Select Ubuntu 20.04
- Select the $5/mo plan
- Select the datacenter region
- Select the SSH key
- Create the droplet
- Copy the droplet IP address
Create Azure Pipeline Variable Group
- Login to Azure DevOps
- Go to Project Settings > Pipelines > Variable Groups
- Create a new variable group
- Add variables
Create docker compose file for app
- Create docker-compose.yml file
- Add the following code to the file
version: '3.8'
services:
web-app:
build:
context: ./web-app
dockerfile: Dockerfile
image: web-app:latest
restart: always
ports:
- "80:80"
environment:
- API_URL=http://service-app:3000
depends_on:
- service-app
service-app:
build:
context: ./service-app
dockerfile: Dockerfile
image: service-app:latest
restart: always
ports:
- "3000:3000"
environment:
- MONGO_URI=mongodb://root:153698ads@mongo:27017/esv_analytics_db?authSource=admin
depends_on:
- mongo
mongo:
image: mongo
restart: always
ports:
- "27017:27017"
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=153698ads
- MONGO_INITDB_DATABASE=esv_analytics_db
volumes:
- mongo-data:/data/db
volumes:
mongo-data:
Create Dockerfile for web-app
- Create Dockerfile file
- Add the following code to the file
FROM node:alpine as builder
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
RUN npm run build
FROM nginx
EXPOSE 80
# copy the default.conf file to the nginx container
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/dist /usr/share/nginx/html
Create Dockerfile for service-app
- Create Dockerfile file
- Add the following code to the file
# Express.js app
FROM node:18-alpine as builder
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
Create nginx config file for web-app
- Create nginx folder
- Create default.conf file
- Add the following code to the file
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}