Operations & Maintenance
Day-to-day commands for managing your deployment.
Verify auto-restart#
Docker's --restart unless-stopped handles container restarts. Ensure Docker itself starts on boot:
sudo systemctl enable dockerReboot test#
sudo reboot
# wait 30 seconds, then SSH back in
docker ps # containers should be running
curl https://DOMAIN/ # app should respondRedeploy (manual)#
Single container#
docker pull GHCR_IMAGE
docker stop CONTAINER_NAME && docker rm CONTAINER_NAME
docker run -d \
--name CONTAINER_NAME \
-p APP_PORT:APP_PORT \
--env-file ~/app.env \
--restart unless-stopped \
GHCR_IMAGEDocker Compose#
cd ~/app
docker compose pull
docker compose up -dRedeploy script#
Create ~/redeploy.sh on your VPS for one-command redeployments:
#!/bin/bash
set -e
# ---- Configure these per project ----
IMAGE="ghcr.io/username/repo:latest"
CONTAINER="myapp"
ENV_FILE="$HOME/app.env"
PORT="8000"
HEALTH_ENDPOINT="/health"
# --------------------------------------
echo "=== Pulling latest image ==="
docker pull "$IMAGE"
echo "=== Stopping and removing old container ==="
docker stop "$CONTAINER" 2>/dev/null || true
docker rm "$CONTAINER" 2>/dev/null || true
echo "=== Starting new container ==="
docker run -d \
--name "$CONTAINER" \
-p "$PORT:$PORT" \
--env-file "$ENV_FILE" \
--restart unless-stopped \
"$IMAGE"
echo "=== Waiting for app to start ==="
sleep 3
echo "=== Health check ==="
curl -sf http://localhost:$PORT$HEALTH_ENDPOINT && echo "" || echo "WARNING: Health check failed"
echo "=== Cleaning up old images ==="
docker image prune -af
echo "=== Done ==="
docker ps --filter "name=$CONTAINER"Make it executable:
chmod +x ~/redeploy.shDocker Compose version#
#!/bin/bash
set -e
cd ~/app
docker compose pull
docker compose up -d
docker image prune -f
docker compose psRollback to a specific SHA#
Images are tagged with sha- prefix by the CI workflow:
docker pull ghcr.io/username/repo:sha-abc1234
docker stop CONTAINER_NAME && docker rm CONTAINER_NAME
docker run -d \
--name CONTAINER_NAME \
-p APP_PORT:APP_PORT \
--env-file ~/app.env \
--restart unless-stopped \
ghcr.io/username/repo:sha-abc1234Update env vars#
nano ~/app.env
# edit values, save
# Restart to pick up changes
docker restart CONTAINER_NAME
# Or for compose
cd ~/app && docker compose restartView logs#
# Single container
docker logs CONTAINER_NAME
docker logs -f CONTAINER_NAME # follow/tail
# Docker Compose
cd ~/app
docker compose logs
docker compose logs -f backend # follow specific serviceNginx logs#
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.logClean up old images#
docker image prune -aRenew SSL manually (usually not needed)#
sudo certbot renew