-
Notifications
You must be signed in to change notification settings - Fork 1
DO-2030: add reusable Docker build and push workflow #162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
a8aa786
DO-2030: add reusable Docker build and push workflow
crispy101 9546126
Split build and push to prevent auth token timeout
crispy101 c2036e3
Add documentation for Docker Build and Push workflow
crispy101 68bb8c0
DO-2030: allow to skip DockerHub authentication in case of no need of…
crispy101 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,168 @@ | ||
| name: Docker Build and Push | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| image-name: | ||
| description: "Docker image name (e.g., aligent/my-app)" | ||
| type: string | ||
| required: true | ||
| registry: | ||
| description: "Docker registry" | ||
| type: string | ||
| required: false | ||
| default: "docker.io" | ||
| context: | ||
| description: "Build context path" | ||
| type: string | ||
| required: false | ||
| default: "." | ||
| dockerfile: | ||
| description: "Path to Dockerfile" | ||
| type: string | ||
| required: false | ||
| default: "Dockerfile" | ||
| build-args: | ||
| description: "Build arguments (newline-separated KEY=value pairs)" | ||
| type: string | ||
| required: false | ||
| default: "" | ||
| platforms: | ||
| description: "Target platforms (e.g., linux/amd64,linux/arm64)" | ||
| type: string | ||
| required: false | ||
| default: "" | ||
| push: | ||
| description: "Push image to registry" | ||
| type: boolean | ||
| required: false | ||
| default: true | ||
| tags: | ||
| description: "Custom tags configuration for docker/metadata-action" | ||
| type: string | ||
| required: false | ||
| default: | | ||
| type=raw,value=latest,enable={{is_default_branch}} | ||
| type=sha,prefix= | ||
| no-cache: | ||
| description: "Disable build cache" | ||
| type: boolean | ||
| required: false | ||
| default: false | ||
| cache-from: | ||
| description: "Cache source (e.g., type=gha)" | ||
| type: string | ||
| required: false | ||
| default: "type=gha" | ||
| cache-to: | ||
| description: "Cache destination (e.g., type=gha,mode=max)" | ||
| type: string | ||
| required: false | ||
| default: "type=gha,mode=max" | ||
| provenance: | ||
| description: "Generate provenance attestation" | ||
| type: boolean | ||
| required: false | ||
| default: false | ||
| timeout-minutes: | ||
| description: "Job timeout in minutes" | ||
| type: number | ||
| required: false | ||
| default: 60 | ||
| dockerhub-username: | ||
| description: "Docker Hub username (from vars). Required when push: true (default)." | ||
| type: string | ||
| required: false | ||
|
|
||
| secrets: | ||
| dockerhub-token: | ||
| description: "Docker Hub access token (from secrets). Required when push: true (default)." | ||
| required: false | ||
| build-secrets: | ||
| description: "Docker BuildKit secrets (newline-separated KEY=value pairs)" | ||
| required: false | ||
| build-args-secrets: | ||
| description: "Secret build arguments appended to build-args (newline-separated KEY=value pairs)" | ||
| required: false | ||
|
|
||
| jobs: | ||
| build-and-push: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: ${{ inputs.timeout-minutes }} | ||
| permissions: | ||
| contents: read | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Set up QEMU | ||
| if: inputs.platforms != '' | ||
| uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 | ||
|
|
||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 | ||
|
|
||
| - name: Log in to Docker Hub | ||
| if: inputs.push | ||
| uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 | ||
| with: | ||
| registry: ${{ inputs.registry }} | ||
| username: ${{ inputs.dockerhub-username }} | ||
| password: ${{ secrets.dockerhub-token }} | ||
|
|
||
| - name: Extract metadata for Docker | ||
| id: meta | ||
| uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 | ||
| with: | ||
| images: ${{ inputs.registry }}/${{ inputs.image-name }} | ||
| tags: ${{ inputs.tags }} | ||
|
|
||
| - name: Prepare build args | ||
| id: build-args | ||
| run: | | ||
| { | ||
| echo 'args<<EOF' | ||
| echo "$BUILD_ARGS" | ||
| echo "$BUILD_ARGS_SECRETS" | ||
| echo 'EOF' | ||
| } >> "$GITHUB_OUTPUT" | ||
| env: | ||
| BUILD_ARGS: ${{ inputs.build-args }} | ||
| BUILD_ARGS_SECRETS: ${{ secrets.build-args-secrets }} | ||
|
|
||
| - name: Build Docker image | ||
| uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 | ||
| with: | ||
| context: ${{ inputs.context }} | ||
| file: ${{ inputs.context }}/${{ inputs.dockerfile }} | ||
| push: false | ||
| load: ${{ inputs.platforms == '' }} | ||
| tags: ${{ steps.meta.outputs.tags }} | ||
| labels: ${{ steps.meta.outputs.labels }} | ||
| build-args: ${{ steps.build-args.outputs.args }} | ||
| platforms: ${{ inputs.platforms || '' }} | ||
| no-cache: ${{ inputs.no-cache }} | ||
| cache-from: ${{ !inputs.no-cache && inputs.cache-from || '' }} | ||
| cache-to: ${{ inputs.cache-to }} | ||
| provenance: ${{ inputs.provenance }} | ||
| secrets: ${{ secrets.build-secrets }} | ||
|
|
||
| - name: Refresh Docker Hub login | ||
| if: inputs.push | ||
| uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 | ||
| with: | ||
| registry: ${{ inputs.registry }} | ||
| username: ${{ inputs.dockerhub-username }} | ||
| password: ${{ secrets.dockerhub-token }} | ||
|
|
||
| - name: Push Docker image | ||
|
AdamJHall marked this conversation as resolved.
|
||
| if: inputs.push | ||
| run: | | ||
| echo "$TAGS" | tr ',' '\n' | while read -r tag; do | ||
| [ -n "$tag" ] && docker push "$tag" | ||
| done | ||
| env: | ||
| TAGS: ${{ steps.meta.outputs.tags }} | ||
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| # Docker Build and Push | ||
|
|
||
| Build and push Docker images to Docker Hub with support for multi-platform builds, caching, and BuildKit secrets. | ||
|
|
||
| #### **Inputs** | ||
| | Name | Required | Type | Default | Description | | ||
| |-------------------|----------|---------|------------------------------------------------------|--------------------------------------------------| | ||
| | image-name | ✅ | string | | Docker image name (e.g., `aligent/my-app`) | | ||
| | registry | ❌ | string | `docker.io` | Docker registry | | ||
| | context | ❌ | string | `.` | Build context path | | ||
| | dockerfile | ❌ | string | `Dockerfile` | Path to Dockerfile | | ||
| | build-args | ❌ | string | | Build arguments (newline-separated KEY=value) | | ||
| | platforms | ❌ | string | | Target platforms (e.g., `linux/amd64,linux/arm64`) | | ||
| | push | ❌ | boolean | `true` | Push image to registry | | ||
| | tags | ❌ | string | `type=raw,value=latest,enable={{is_default_branch}}`<br>`type=sha,prefix=` | Custom tags for docker/metadata-action | | ||
| | no-cache | ❌ | boolean | `false` | Disable build cache | | ||
| | cache-from | ❌ | string | `type=gha` | Cache source | | ||
| | cache-to | ❌ | string | `type=gha,mode=max` | Cache destination | | ||
| | provenance | ❌ | boolean | `false` | Generate provenance attestation | | ||
| | timeout-minutes | ❌ | number | `60` | Job timeout in minutes | | ||
| | dockerhub-username| ✅ | string | | Docker Hub username (from vars) | | ||
|
|
||
| #### **Secrets** | ||
| | Name | Required | Description | | ||
| |-------------------|----------|------------------------------------------------------| | ||
| | dockerhub-token | ✅ | Docker Hub access token | | ||
| | build-secrets | ❌ | Docker BuildKit secrets (newline-separated KEY=value)| | ||
| | build-args-secrets| ❌ | Secret build arguments appended to build-args | | ||
|
|
||
| #### **Features** | ||
|
|
||
| - **Split build and push**: Build and push are separate steps with a fresh Docker Hub login before push, preventing token timeout for long-running builds. | ||
| - **Multi-platform support**: Optional QEMU setup for cross-platform builds. | ||
| - **GitHub Actions cache**: Uses `type=gha` caching by default for faster builds. | ||
| - **BuildKit secrets**: Securely pass secrets during build without exposing them in logs. | ||
| - **Flexible tagging**: Uses docker/metadata-action for automatic tag generation. | ||
|
|
||
| #### Example Usage | ||
|
|
||
| ```yaml | ||
| name: Build and Push Docker Image | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
| schedule: | ||
| - cron: '0 2 * * *' # Daily at 2am UTC | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
| build-and-push: | ||
| uses: aligent/workflows/.github/workflows/docker-build.yml@main | ||
| with: | ||
| image-name: aligent/my-app | ||
| dockerhub-username: ${{ vars.DOCKERHUB_USERNAME }} | ||
| build-args: | | ||
| BUILD_ENV=production | ||
| secrets: | ||
| dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }} | ||
| ``` | ||
|
|
||
| #### Example with BuildKit Secrets | ||
|
|
||
| For builds requiring sensitive data (e.g., API keys during build): | ||
|
|
||
| ```yaml | ||
| jobs: | ||
| build-and-push: | ||
| uses: aligent/workflows/.github/workflows/docker-build.yml@main | ||
| with: | ||
| image-name: aligent/my-app | ||
| dockerhub-username: ${{ vars.DOCKERHUB_USERNAME }} | ||
| timeout-minutes: 360 | ||
| build-args: | | ||
| UPDATE_DB=true | ||
| secrets: | ||
| dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }} | ||
| build-secrets: | | ||
| NVD_API_KEY=${{ secrets.NVD_API_KEY }} | ||
| ``` | ||
|
|
||
| In your Dockerfile, access the secret: | ||
|
|
||
| ```dockerfile | ||
| RUN --mount=type=secret,id=NVD_API_KEY,mode=0444 \ | ||
| SECRET_VALUE=$(cat /run/secrets/NVD_API_KEY) && \ | ||
| # use SECRET_VALUE... | ||
| ``` | ||
|
|
||
| #### Example with Multi-Platform Build | ||
|
|
||
| ```yaml | ||
| jobs: | ||
| build-and-push: | ||
| uses: aligent/workflows/.github/workflows/docker-build.yml@main | ||
| with: | ||
| image-name: aligent/my-app | ||
| dockerhub-username: ${{ vars.DOCKERHUB_USERNAME }} | ||
| platforms: linux/amd64,linux/arm64 | ||
| secrets: | ||
| dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }} | ||
| ``` |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.