| 1 | # This workflow builds and publishes official Docker images to Docker Hub. |
| 2 | # It handles multi-platform builds (amd64, arm/v7, arm64/v8) and pushes tagged releases. |
| 3 | # This workflow is triggered on tags, specific branches, and can be manually dispatched. |
| 4 | # For quick build checks during development, see docker-check.yml |
| 5 | name: Docker Push |
| 6 | |
| 7 | on: |
| 8 | workflow_dispatch: |
| 9 | inputs: |
| 10 | push: |
| 11 | description: 'Push to Docker Hub' |
| 12 | required: true |
| 13 | default: 'false' |
| 14 | tags: |
| 15 | description: 'Custom tags to use for the push' |
| 16 | required: false |
| 17 | default: '' |
| 18 | # # If we decide to build all images on every PR, we should make sure that |
| 19 | # # they are NOT pushed to Docker Hub. |
| 20 | # pull_request: |
| 21 | # paths-ignore: |
| 22 | # - '**/*.md' |
| 23 | push: |
| 24 | branches: |
| 25 | - 'master' |
| 26 | - 'staging' |
| 27 | - 'bifrost-*' |
| 28 | tags: |
| 29 | - 'v*' |
| 30 | |
| 31 | permissions: |
| 32 | contents: read # to fetch code (actions/checkout) |
| 33 | |
| 34 | jobs: |
| 35 | docker-hub: |
| 36 | if: github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch' |
| 37 | name: Push Docker image to Docker Hub |
| 38 | runs-on: ubuntu-latest |
| 39 | timeout-minutes: 15 |
| 40 | env: |
| 41 | IMAGE_NAME: ipfs/kubo |
| 42 | outputs: |
| 43 | tags: ${{ steps.tags.outputs.value }} |
| 44 | steps: |
| 45 | - name: Check out the repo |
| 46 | uses: actions/checkout@v6 |
| 47 | |
| 48 | - name: Set up QEMU |
| 49 | uses: docker/setup-qemu-action@v4 |
| 50 | |
| 51 | - name: Set up Docker Buildx |
| 52 | uses: docker/setup-buildx-action@v4 |
| 53 | |
| 54 | - name: Log in to Docker Hub |
| 55 | uses: docker/login-action@v4 |
| 56 | with: |
| 57 | username: ${{ vars.DOCKER_USERNAME }} |
| 58 | password: ${{ secrets.DOCKER_PASSWORD }} |
| 59 | |
| 60 | - name: Get tags |
| 61 | id: tags |
| 62 | if: github.event.inputs.tags == '' |
| 63 | run: | |
| 64 | echo "value<<EOF" >> $GITHUB_OUTPUT |
| 65 | ./bin/get-docker-tags.sh "$(date -u +%F)" >> $GITHUB_OUTPUT |
| 66 | echo "EOF" >> $GITHUB_OUTPUT |
| 67 | shell: bash |
| 68 | |
| 69 | # Read the Go version from go.mod so the Docker image is built with the |
| 70 | # exact same toolchain that setup-go installs in the rest of CI. |
| 71 | - name: Read Go version from go.mod |
| 72 | id: go |
| 73 | run: echo "version=$(awk '/^go [0-9]/ {print $2; exit}' go.mod)" >> "$GITHUB_OUTPUT" |
| 74 | |
| 75 | # We have to build each platform separately because when using multi-arch |
| 76 | # builds, only one platform is being loaded into the cache. This would |
| 77 | # prevent us from testing the other platforms. |
| 78 | - name: Build Docker image (linux/amd64) |
| 79 | uses: docker/build-push-action@v7 |
| 80 | with: |
| 81 | platforms: linux/amd64 |
| 82 | context: . |
| 83 | push: false |
| 84 | load: true |
| 85 | file: ./Dockerfile |
| 86 | tags: ${{ env.IMAGE_NAME }}:linux-amd64 |
| 87 | build-args: | |
| 88 | GO_VERSION=${{ steps.go.outputs.version }} |
| 89 | cache-from: | |
| 90 | type=gha |
| 91 | type=registry,ref=${{ env.IMAGE_NAME }}:buildcache |
| 92 | cache-to: type=gha,mode=max |
| 93 | |
| 94 | - name: Build Docker image (linux/arm/v7) |
| 95 | uses: docker/build-push-action@v7 |
| 96 | with: |
| 97 | platforms: linux/arm/v7 |
| 98 | context: . |
| 99 | push: false |
| 100 | load: true |
| 101 | file: ./Dockerfile |
| 102 | tags: ${{ env.IMAGE_NAME }}:linux-arm-v7 |
| 103 | build-args: | |
| 104 | GO_VERSION=${{ steps.go.outputs.version }} |
| 105 | cache-from: | |
| 106 | type=gha |
| 107 | type=registry,ref=${{ env.IMAGE_NAME }}:buildcache |
| 108 | cache-to: type=gha,mode=max |
| 109 | |
| 110 | - name: Build Docker image (linux/arm64/v8) |
| 111 | uses: docker/build-push-action@v7 |
| 112 | with: |
| 113 | platforms: linux/arm64/v8 |
| 114 | context: . |
| 115 | push: false |
| 116 | load: true |
| 117 | file: ./Dockerfile |
| 118 | tags: ${{ env.IMAGE_NAME }}:linux-arm64-v8 |
| 119 | build-args: | |
| 120 | GO_VERSION=${{ steps.go.outputs.version }} |
| 121 | cache-from: | |
| 122 | type=gha |
| 123 | type=registry,ref=${{ env.IMAGE_NAME }}:buildcache |
| 124 | cache-to: type=gha,mode=max |
| 125 | |
| 126 | # We test all the images on amd64 host here. This uses QEMU to emulate |
| 127 | # the other platforms. |
| 128 | # NOTE: --version should finish instantly, but sometimes |
| 129 | # it hangs on github CI (could be qemu issue), so we retry to remove false negatives |
| 130 | - name: Smoke-test linux-amd64 |
| 131 | run: for i in {1..3}; do timeout 15s docker run --rm $IMAGE_NAME:linux-amd64 version --all && break || [ $i = 3 ] && exit 1; done |
| 132 | timeout-minutes: 1 |
| 133 | - name: Smoke-test linux-arm-v7 |
| 134 | run: for i in {1..3}; do timeout 15s docker run --rm $IMAGE_NAME:linux-arm-v7 version --all && break || [ $i = 3 ] && exit 1; done |
| 135 | timeout-minutes: 1 |
| 136 | - name: Smoke-test linux-arm64-v8 |
| 137 | run: for i in {1..3}; do timeout 15s docker run --rm $IMAGE_NAME:linux-arm64-v8 version --all && break || [ $i = 3 ] && exit 1; done |
| 138 | timeout-minutes: 1 |
| 139 | |
| 140 | # This will only push the previously built images. |
| 141 | - if: github.event_name != 'workflow_dispatch' || github.event.inputs.push == 'true' |
| 142 | name: Publish to Docker Hub |
| 143 | uses: docker/build-push-action@v7 |
| 144 | with: |
| 145 | platforms: linux/amd64,linux/arm/v7,linux/arm64/v8 |
| 146 | context: . |
| 147 | push: true |
| 148 | file: ./Dockerfile |
| 149 | tags: "${{ github.event.inputs.tags || steps.tags.outputs.value }}" |
| 150 | build-args: | |
| 151 | GO_VERSION=${{ steps.go.outputs.version }} |
| 152 | cache-from: | |
| 153 | type=gha |
| 154 | type=registry,ref=${{ env.IMAGE_NAME }}:buildcache |
| 155 | cache-to: | |
| 156 | type=gha,mode=max |
| 157 | type=registry,ref=${{ env.IMAGE_NAME }}:buildcache,mode=max |