Auto Deploy to Server #272
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 }} | |
| DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} | |
| with: | |
| host: ${{ secrets.SERVER_HOST }} | |
| username: ${{ secrets.SERVER_USERNAME }} | |
| port: ${{ secrets.SERVER_PORT }} | |
| password: ${{ secrets.SERVER_PASSWORD }} | |
| command_timeout: 30m | |
| envs: DOCKER_USERNAME,DOCKER_PASSWORD | |
| 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 | |
| # Login to Docker Hub | |
| echo "π Logging in to Docker Hub..." | |
| echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USERNAME}" --password-stdin || { | |
| echo "β Docker login failed" | |
| exit 1 | |
| } | |
| # Get remote image digest | |
| echo "π Checking for updates..." | |
| REMOTE_DIGEST=$(docker manifest inspect "$IMAGE" 2>/dev/null | grep -m1 '"digest"' | cut -d'"' -f4) | |
| if [ -z "$REMOTE_DIGEST" ]; then | |
| echo "β Failed to fetch remote image info" | |
| exit 1 | |
| fi | |
| # Get current running container digest | |
| CURRENT_DIGEST=$(docker inspect docflow 2>/dev/null | grep -m1 '"Image"' | cut -d'"' -f4 | xargs docker inspect 2>/dev/null | grep -m1 '"Id"' | cut -d'"' -f4) | |
| # Compare digests | |
| if [ "$REMOTE_DIGEST" = "$CURRENT_DIGEST" ]; then | |
| echo "β Already running latest version" | |
| exit 0 | |
| fi | |
| echo "π New version available, deploying..." | |
| # Pull new image | |
| docker pull "$IMAGE" || exit 1 | |
| # 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 |