Update Dockerfile #11
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Build and Push Docker Image to DigitalOcean Droplet | |
on: | |
push: | |
branches: [master, main] # Trigger on both master and main | |
jobs: | |
deploy: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 # Upgraded to v4 | |
- name: Set up Docker Image Tag | |
run: | | |
echo "IMAGE_TAG=todoapp:$(date +%s)-${GITHUB_SHA::8}" >> $GITHUB_ENV | |
- name: Build Docker image | |
run: | | |
docker build -t "${{ env.IMAGE_TAG }}" . | |
docker image ls | grep "${{ env.IMAGE_TAG }}" | |
- name: Save Docker image to a tar file | |
run: | | |
docker save ${{ env.IMAGE_TAG }} -o image.tar | |
ls -lh image.tar | |
- name: Setup SSH | |
env: | |
SSH_PRIVATE_KEY: ${{ secrets.DROPLET_SSH_KEY }} | |
KNOWN_HOSTS: ${{ secrets.KNOWN_HOSTS }} | |
run: | | |
mkdir -p ~/.ssh | |
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa | |
chmod 600 ~/.ssh/id_rsa | |
echo "$KNOWN_HOSTS" > ~/.ssh/known_hosts | |
- name: Transfer Docker image to DigitalOcean droplet | |
env: | |
HOST: ${{ secrets.DROPLET_IP }} | |
USERNAME: ${{ secrets.DROPLET_USERNAME }} | |
run: | | |
scp -i ~/.ssh/id_rsa image.tar ${USERNAME}@${HOST}:/home/${USERNAME}/image.tar | |
- name: SSH into Droplet and Deploy | |
env: | |
HOST: ${{ secrets.DROPLET_IP }} | |
USERNAME: ${{ secrets.DROPLET_USERNAME }} | |
run: | | |
ssh -i ~/.ssh/id_rsa ${USERNAME}@${HOST} << EOF | |
set -e # Exit immediately if a command exits with a non-zero status | |
echo "Loading Docker image..." | |
sudo docker load -i /home/${USERNAME}/image.tar | |
echo "Stopping and removing existing container..." | |
sudo docker stop my-container || true | |
sudo docker rm my-container || true | |
echo "Creating Docker secrets..." | |
echo "${{ secrets.MONGO_CONNECTION_STRING }}" | sudo docker secret create mongo_connection_string - || true | |
echo "${{ secrets.MONGO_DATABASE_NAME }}" | sudo docker secret create mongo_database_name - || true | |
echo "${{ secrets.MONGO_COLLECTION_NAME }}" | sudo docker secret create mongo_collection_name - || true | |
echo "Deploying new container..." | |
sudo docker run -d --name my-container -p 8081:8080 \ | |
--secret mongo_connection_string \ | |
--secret mongo_database_name \ | |
--secret mongo_collection_name \ | |
--health-cmd="curl -f http://localhost:8080/health || exit 1" \ | |
--health-interval=30s \ | |
--health-timeout=10s \ | |
--health-retries=3 \ | |
${{ env.IMAGE_TAG }} | |
echo "Waiting for container to be healthy..." | |
timeout 300s bash -c 'while [[ "$(sudo docker inspect -f {{.State.Health.Status}} my-container)" != "healthy" ]]; do sleep 5; done' || (echo "Container failed to become healthy" && exit 1) | |
echo "Verifying container is running..." | |
sudo docker ps | grep my-container | |
echo "Cleaning up..." | |
rm /home/${USERNAME}/image.tar | |
echo "Deployment completed successfully!" | |
EOF | |
- name: Verify Deployment | |
env: | |
HOST: ${{ secrets.DROPLET_IP }} | |
USERNAME: ${{ secrets.DROPLET_USERNAME }} | |
run: | | |
ssh -i ~/.ssh/id_rsa ${USERNAME}@${HOST} "curl -sSf http://localhost:8081/health || (echo 'Health check failed' && exit 1)" | |
- name: Rollback on Failure | |
if: failure() | |
env: | |
HOST: ${{ secrets.DROPLET_IP }} | |
USERNAME: ${{ secrets.DROPLET_USERNAME }} | |
run: | | |
ssh -i ~/.ssh/id_rsa ${USERNAME}@${HOST} << EOF | |
echo "Deployment failed. Rolling back..." | |
sudo docker stop my-container || true | |
sudo docker rm my-container || true | |
sudo docker run -d --name my-container -p 8081:8080 \ | |
--secret mongo_connection_string \ | |
--secret mongo_database_name \ | |
--secret mongo_collection_name \ | |
$(sudo docker images --format "{{.Repository}}:{{.Tag}}" | grep todoapp | head -n 2 | tail -n 1) | |
echo "Rollback completed." | |
EOF |