Auto Deploy to Server #282
This file contains hidden or 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: Auto Deploy to Server | |
| on: | |
| schedule: | |
| - cron: '0 16 */2 * *' # Every 2 days at 00:00 Beijing Time (16:00 UTC) | |
| workflow_dispatch: # Allow manual trigger | |
| jobs: | |
| check-and-deploy: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check for new Docker image and deploy | |
| uses: appleboy/ssh-action@v1.2.1 | |
| env: | |
| DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} | |
| with: | |
| host: ${{ secrets.SERVER_HOST }} | |
| username: ${{ secrets.SERVER_USERNAME }} | |
| port: ${{ secrets.SERVER_PORT }} | |
| password: ${{ secrets.SERVER_PASSWORD }} | |
| command_timeout: 30m | |
| envs: DOCKER_USERNAME | |
| script: | | |
| IMAGE="${DOCKER_USERNAME}/docflow:latest" | |
| # Configure Docker mirrors (only if not configured) | |
| if [ ! -f /etc/docker/daemon.json ] || ! grep -q "registry-mirrors" /etc/docker/daemon.json; then | |
| echo "βοΈ Configuring Docker mirrors..." | |
| sudo tee /etc/docker/daemon.json > /dev/null <<'EOF' | |
| { | |
| "registry-mirrors": [ | |
| "https://docker.m.daocloud.io", | |
| "https://docker.1panel.live", | |
| "https://hub.rat.dev" | |
| ] | |
| } | |
| EOF | |
| sudo systemctl daemon-reload | |
| sudo systemctl restart docker | |
| sleep 5 | |
| fi | |
| # Record current running container's image ID | |
| RUNNING_IMAGE_ID=$(docker inspect docflow --format='{{.Image}}' 2>/dev/null || echo "none") | |
| echo "π Current running image: ${RUNNING_IMAGE_ID}" | |
| # Pull latest image (goes through mirrors, no login needed for public images) | |
| echo "π Pulling latest image..." | |
| docker pull "$IMAGE" || exit 1 | |
| # Get the pulled image ID | |
| LATEST_IMAGE_ID=$(docker inspect "$IMAGE" --format='{{.Id}}' 2>/dev/null) | |
| echo "π¦ Latest pulled image: ${LATEST_IMAGE_ID}" | |
| # Compare: if running container already uses the latest image, skip | |
| if [ "$RUNNING_IMAGE_ID" = "$LATEST_IMAGE_ID" ]; then | |
| echo "β Already running latest version" | |
| exit 0 | |
| fi | |
| echo "π New version detected, deploying..." | |
| # Stop and remove old container | |
| docker stop docflow 2>/dev/null || true | |
| docker rm docflow 2>/dev/null || true | |
| # Start new container | |
| CONTAINER_ID=$(docker run -d \ | |
| --name docflow \ | |
| --restart unless-stopped \ | |
| -p 3000:3000 \ | |
| -e NODE_ENV=production \ | |
| "$IMAGE") | |
| if [ -z "$CONTAINER_ID" ]; then | |
| echo "β Failed to start container" | |
| exit 1 | |
| fi | |
| # Wait and verify | |
| sleep 5 | |
| CONTAINER_STATUS=$(docker inspect -f '{{.State.Status}}' docflow 2>/dev/null) | |
| if [ "$CONTAINER_STATUS" = "running" ]; then | |
| echo "β Deployment successful" | |
| docker logs --tail 20 docflow | |
| else | |
| echo "β Container failed to start" | |
| docker logs docflow 2>&1 | |
| exit 1 | |
| fi | |
| # Clean up old dangling images | |
| docker image prune -f 2>/dev/null || true |