aboutsummaryrefslogtreecommitdiff
path: root/.github/workflows/container_latest.yml
blob: 7d8868f35f79d282c81dd75ca2c3a3d5d43fdd6d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
name: "docker: build latest container"

on:
  push:
    tags:
      - '*'
  workflow_dispatch: {}

permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        platform: [amd64, arm64, arm, 386]
        include:
          - platform: amd64
            qemu: false
          - platform: arm64
            qemu: true
          - platform: arm
            qemu: true
          - platform: 386
            qemu: true
    steps:
      - name: Checkout
        uses: actions/checkout@v6
      - name: Free Disk Space
        run: |
          echo "Available disk space before cleanup:"
          df -h
          # Remove pre-installed tools
          sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL
          # Clean package managers
          sudo apt-get clean
          sudo rm -rf /var/lib/apt/lists/*
          # Clean Docker aggressively
          sudo docker system prune -af --volumes
          # Clean Go cache if it exists
          [ -d ~/.cache/go-build ] && rm -rf ~/.cache/go-build || true
          [ -d /go/pkg ] && rm -rf /go/pkg || true
          echo "Available disk space after cleanup:"
          df -h
      - name: Docker meta
        id: docker_meta
        uses: docker/metadata-action@v5
        with:
          images: |
            chrislusf/seaweedfs
            ghcr.io/chrislusf/seaweedfs
          tags: type=raw,value=latest
          labels: |
            org.opencontainers.image.title=seaweedfs
            org.opencontainers.image.description=SeaweedFS is a distributed storage system for blobs, objects, files, and data lake, to store and serve billions of files fast!
            org.opencontainers.image.vendor=Chris Lu
      - name: Set up QEMU
        if: matrix.qemu
        uses: docker/setup-qemu-action@v3
      - name: Create BuildKit config
        run: |
          cat > /tmp/buildkitd.toml <<EOF
          [registry."docker.io"]
            mirrors = ["https://mirror.gcr.io"]
          EOF
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          buildkitd-flags: "--debug"
          buildkitd-config: /tmp/buildkitd.toml
      - name: Login to Docker Hub
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      - name: Login to GHCR
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ secrets.GHCR_USERNAME }}
          password: ${{ secrets.GHCR_TOKEN }}
      - name: Build ${{ matrix.platform }}
        uses: docker/build-push-action@v6
        env:
          DOCKER_BUILDKIT: 1
        with:
          context: ./docker
          push: ${{ github.event_name != 'pull_request' }}
          file: ./docker/Dockerfile.go_build
          platforms: linux/${{ matrix.platform }}
          # Push to GHCR only during build to avoid Docker Hub rate limits
          tags: ghcr.io/chrislusf/seaweedfs:latest-${{ matrix.platform }}
          labels: ${{ steps.docker_meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          build-args: |
            BUILDKIT_INLINE_CACHE=1
            BRANCH=${{ github.sha }}
      - name: Clean up build artifacts
        if: always()
        run: |
          # Clean up Docker build cache and temporary files
          sudo docker system prune -f
          # Remove Go build cache
          sudo rm -rf /tmp/go-build*

  create-manifest:
    runs-on: ubuntu-latest
    needs: [build]
    if: github.event_name != 'pull_request'
    steps:
      - name: Checkout
        uses: actions/checkout@v6
      - name: Docker meta
        id: docker_meta
        uses: docker/metadata-action@v5
        with:
          images: |
            chrislusf/seaweedfs
            ghcr.io/chrislusf/seaweedfs
          tags: type=raw,value=latest
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ secrets.GHCR_USERNAME }}
          password: ${{ secrets.GHCR_TOKEN }}
      - name: Install crane
        run: |
          # Install crane for efficient multi-arch image copying
          cd $(mktemp -d)
          curl -sL "https://github.com/google/go-containerregistry/releases/latest/download/go-containerregistry_Linux_x86_64.tar.gz" | tar xz
          sudo mv crane /usr/local/bin/
          crane version
      - name: Create and push manifest
        run: |
          # Create manifest on GHCR first (no rate limits)
          echo "Creating GHCR manifest (no rate limits)..."
          docker buildx imagetools create -t ghcr.io/chrislusf/seaweedfs:latest \
            ghcr.io/chrislusf/seaweedfs:latest-amd64 \
            ghcr.io/chrislusf/seaweedfs:latest-arm64 \
            ghcr.io/chrislusf/seaweedfs:latest-arm \
            ghcr.io/chrislusf/seaweedfs:latest-386
          
          # Copy the complete multi-arch image from GHCR to Docker Hub
          # This only requires one pull from GHCR (no rate limit) and one push to Docker Hub
          echo "Copying manifest from GHCR to Docker Hub..."
          
          # Function to retry with exponential backoff for Docker Hub operations
          retry_with_backoff() {
            local max_attempts=5
            local timeout=1
            local attempt=1
            local exit_code=0
            
            while [ $attempt -le $max_attempts ]; do
              if "$@"; then
                return 0
              else
                exit_code=$?
              fi
              
              if [ $attempt -lt $max_attempts ]; then
                echo "Attempt $attempt failed. Retrying in ${timeout}s..." >&2
                sleep $timeout
                timeout=$((timeout * 2))
              fi
              
              attempt=$((attempt + 1))
            done
            
            echo "Command failed after $max_attempts attempts" >&2
            return $exit_code
          }
          
          # Use crane or skopeo to copy, fallback to docker if not available
          if command -v crane &> /dev/null; then
            echo "Using crane to copy..."
            retry_with_backoff crane copy ghcr.io/chrislusf/seaweedfs:latest chrislusf/seaweedfs:latest
          elif command -v skopeo &> /dev/null; then
            echo "Using skopeo to copy..."
            retry_with_backoff skopeo copy --all docker://ghcr.io/chrislusf/seaweedfs:latest docker://chrislusf/seaweedfs:latest
          else
            echo "Using docker buildx imagetools (pulling 4 images from Docker Hub)..."
            # Fallback: create manifest directly on Docker Hub (pulls from Docker Hub - rate limited)
            retry_with_backoff docker buildx imagetools create -t chrislusf/seaweedfs:latest \
              ghcr.io/chrislusf/seaweedfs:latest-amd64 \
              ghcr.io/chrislusf/seaweedfs:latest-arm64 \
              ghcr.io/chrislusf/seaweedfs:latest-arm \
              ghcr.io/chrislusf/seaweedfs:latest-386
          fi