Skip to content

Commit

Permalink
feat: add bash script for zero downtime deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
NishaSharma14 committed Jun 16, 2023
1 parent 4161552 commit 94d31f1
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 7 deletions.
63 changes: 63 additions & 0 deletions ops/docker-compose-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
version: "3.8"

services:
traefik:
image: traefik:v2.10
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- 80:80
# - 8080:8080 # Optional: Expose Traefik dashboard on port 8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock

web:
image: caffeinejena/cheminfo-microservice:dev-latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.web.rule=Host(`dev.api.naturalproducts.net`)"
- "traefik.http.routers.web.entrypoints=web"
- "traefik.http.services.web.loadbalancer.server.port=80"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80/latest/chem"]
interval: 1m
timeout: 10s
retries: 10
start_period: 40s

prometheus:
image: prom/prometheus
container_name: prometheus
ports:
- 9090:9090
volumes:
- ./prometheus_data/prometheus.yml:/etc/prometheus/prometheus.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
grafana:
image: grafana/grafana
container_name: grafana
ports:
- 3000:3000
volumes:
- /mnt/data/grafana_data:/var/lib/grafana
volumes:
prometheus_data:
driver: local
driver_opts:
o: bind
type: none
device: /mnt/data/prometheus_data
grafana_data:
driver: local
driver_opts:
o: bind
type: none
device: /mnt/data/grafana_data
postgres_data:
networks:
default:
name: cpm_fastapi
14 changes: 7 additions & 7 deletions docker-compose-prod.yml → ops/docker-compose-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ services:
traefik:
image: traefik:v2.10
command:
- --api.insecure=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- 80:80
- 8080:8080 # Optional: Expose Traefik dashboard on port 8080
# - 8080:8080 # Optional: Expose Traefik dashboard on port 8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock

web:
image: caffeinejena/cheminfo-microservice:dev-latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.web.rule=Host(`nfdi4chem-oss1-vm11.ianchm.uni-jena.de`)"
- "traefik.http.routers.web.rule=Host(`api.naturalproducts.net`)"
- "traefik.http.routers.web.entrypoints=web"
- "traefik.http.services.web.loadbalancer.server.port=80"
healthcheck:
Expand Down
94 changes: 94 additions & 0 deletions ops/zero-downtime-deploy-bash-script.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/bin/bash

# Define variables
COMPOSE_FILE="/mnt/data/cheminformatics-python-microservice/docker-compose-dev.yml"
DOCKER_REPO_NAME="caffeinejena/cheminfo-microservice:dev-latest"
IMAGE_NAME="caffeinejena/cheminfo-microservice:dev-latest"
NEW_CONTAINER_ID=""
IS_CONTAINER_HEALTHY=1

# Function to check the health of the container
check_health() {

HEALTH=$(docker inspect --format='{{json .State.Health.Status}}' $NEW_CONTAINER_ID)

if [[ $HEALTH == *"healthy"* ]]; then
echo "Container is healthy."
return 0
else
echo "Container is unhealthy or still starting"
return 1
fi

}

# Check if there is a new image available in the Docker repository
if [ "$(docker pull $DOCKER_REPO_NAME | grep "Status: Image is up to date" | wc -l)" -eq 0 ]; then
# Pull the latest image
echo "Pull the latest image.."
docker-compose -f $COMPOSE_FILE pull

# Scale up a new container
echo "Scale up new container.."
docker-compose -f $COMPOSE_FILE up -d --scale web=2 --no-recreate

NEW_CONTAINER_ID=$(docker ps -q -l)

echo "New Container Id is.."
echo "$NEW_CONTAINER_ID"

# Wait for new containers to start and health checks to pass
echo "Waiting for the new containers to start and health check to pass retry 5 times.."
n=0;
while [ $n -le 10 ]
do
if ! check_health; then
n=$(( $n + 1 ))
sleep 1m
echo "Container not healthy.. Check once more.."
else
IS_CONTAINER_HEALTHY=0
break
fi
done

# Remove old containers and images
if [ $IS_CONTAINER_HEALTHY == 0 ] ; then

# Get the container IDs of running containers with the same image
container_ids=$(docker ps --filter ancestor=$IMAGE_NAME --format "{{.ID}}")

# Check if there are exactly two containers running with the same image
if [[ $(echo "$container_ids" | wc -l) -eq 2 ]]; then

# Get the creation timestamps of the two containers
timestamp1=$(docker inspect --format="{{.Created}}" $container_ids | head -n 1)
timestamp2=$(docker inspect --format="{{.Created}}" $container_ids | tail -n 1)

# Compare the timestamps to determine the older container
if [[ "$timestamp1" < "$timestamp2" ]]; then
container_to_delete=$container_ids
else
container_to_delete=$(echo "$container_ids" | tail -n 1)
fi

# Delete the older container and images
docker stop $container_to_delete
docker rm $container_to_delete
docker image prune -af

echo "Deleted container $container_to_delete"

else
echo "Two running containers with the same image not found"
fi

else
echo "Couldnot complete the deployment as the container is unhealthy.."
docker stop $NEW_CONTAINER_ID
docker rm $NEW_CONTAINER_ID
fi

else
echo "Skipping deployment as no new image available.."
fi

0 comments on commit 94d31f1

Please sign in to comment.