GitHub Actions can build and push Docker images for you, but it’s not as straightforward as it looks. The trick is realizing that GitHub Actions runners are ephemeral and don’t have Docker installed by default, and then figuring out how to authenticate with your container registry securely.
name: Build and Push Docker Image
on:
push:
branches:
- main
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
file: ./Dockerfile
push: true
tags: your-dockerhub-username/your-repo-name:latest
This workflow automates the process of building a Docker image from your Dockerfile and pushing it to a registry like Docker Hub.
How it Works:
- Checkout code: This step pulls your repository’s code into the GitHub Actions runner. This is essential so the
Dockerfileand any build context are available. - Set up Docker Buildx: GitHub Actions runners don’t come with Docker installed.
docker/setup-buildx-actioninstalls and configures the BuildKit builder, which is a more efficient and feature-rich Docker image builder. It enables advanced features like multi-platform builds and better caching. - Login to Docker Hub: This step is crucial for pushing your image. It uses
docker/login-actionto authenticate with your container registry. You’ll need to store your Docker Hub username and an access token (not your password!) as GitHub secrets.- Why an access token? Using an access token is more secure than your actual password. You can generate these in your Docker Hub account settings under "Security" -> "Access Tokens." Grant it "Write" permissions.
- How to set up secrets: Go to your GitHub repository’s "Settings" -> "Secrets and variables" -> "Actions." Click "New repository secret" and add
DOCKERHUB_USERNAMEwith your Docker ID andDOCKERHUB_TOKENwith your generated access token.
- Build and push Docker image: The
docker/build-push-actiondoes the heavy lifting.context: .: Specifies the build context, which is the current directory where theDockerfileresides.file: ./Dockerfile: Points to your Dockerfile.push: true: Tells the action to push the built image to the registry.tags: your-dockerhub-username/your-repo-name:latest: This defines the image name and tag. Replaceyour-dockerhub-usernamewith your Docker Hub username andyour-repo-namewith the desired name for your image.:latestis a common tag, but you could use commit SHAs, branch names, or version numbers for more specific tracking.
The Mental Model:
Think of GitHub Actions as a temporary, clean Linux environment that can execute commands. When you use actions like docker/setup-buildx-action or docker/login-action, you’re not installing Docker on your machine; you’re instructing the GitHub runner to download and configure the necessary tools for that specific job run. The build-push-action then leverages these tools to build your image and push it using the credentials you provided.
The ephemeral nature of runners means that each workflow run starts with a blank slate. This is great for consistency but means you can’t rely on anything being pre-installed or pre-configured between runs. Actions abstract away the complexity of setting up these environments.
The Hidden Gem:
The docker/build-push-action can also build multi-platform images if you configure BuildKit correctly and specify multiple --platform arguments. This is incredibly useful if you need your Docker image to run on different architectures (like amd64 for most desktops and arm64 for M1/M2 Macs or Raspberry Pis) without manually managing separate builds. You’d typically add a platforms argument to the build-push-action step, like platforms: linux/amd64,linux/arm64.
The next step is often setting up automated testing of your Docker image after it’s pushed.