Customizing a Standard Docker Image and Pushing to AWS ECR with GitHub Actions
Using pre-built Docker images is convenient, but sometimes, we need to customize a standard Docker image to fit our needs—whether by adding custom CSS, modifying configurations, or installing dependencies.
In this guide, we’ll customize Grafana, add a custom CSS file, and push our modified image to Amazon Elastic Container Registry (ECR) using GitHub Actions with OpenID authentication (OIDC). This approach removes the need for AWS access keys, making deployments more secure.
Step 1: Customizing the Grafana Docker Image
To modify Grafana and add custom styling, we need to extend the base image and inject our files.
1.1 Create a Custom Dockerfile
We’ll start by creating a Dockerfile
that extends the official Grafana image and adds our custom CSS:
FROM grafana/grafana:latest # Copy custom CSS to the correct location COPY custom-style.css /usr/share/grafana/public/css/custom-style.css # Set file permissions RUN chmod 644 /usr/share/grafana/public/css/custom-style.css
Step 2: Building and Testing Locally
Before pushing the image to AWS ECR, we should test it locally:
docker build -t my-custom-grafana . docker run -d -p 3000:3000 my-custom-grafana
If everything looks good, we can automate the build and push process using GitHub Actions.
Step 3: Setting Up AWS OpenID Connect (OIDC) for GitHub
Instead of using AWS access keys, we’ll authenticate GitHub Actions using AWS OpenID Connect (OIDC).
3.1 Create an IAM Role for GitHub Actions
First, create a trust policy (github-oidc-trust-policy.json
):
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringLike": { "token.actions.githubusercontent.com:sub": "repo:<GITHUB_USER>/<REPO>:ref:refs/heads/main" } } } ] }
Then, create the IAM Role:
aws iam create-role --role-name GitHubActionsECRRole \ --assume-role-policy-document file://github-oidc-trust-policy.json
3.2 Attach Permissions to Push to ECR
Create a permissions policy (github-ecr-policy.json
):
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", "ecr:PutImage", "ecr:InitiateLayerUpload", "ecr:UploadLayerPart", "ecr:CompleteLayerUpload" ], "Resource": "*" } ] }
Attach this policy to the IAM role:
aws iam put-role-policy --role-name GitHubActionsECRRole \ --policy-name GitHubECRPushPolicy \ --policy-document file://github-ecr-policy.json
Step 4: Creating the AWS ECR Repository
Before pushing our Docker image, we need to create an ECR repository:
aws ecr create-repository --repository-name my-custom-grafana
Step 5: Automating Image Push with GitHub Actions
Now, we’ll create a GitHub Actions workflow that builds and pushes our custom Grafana image to AWS ECR whenever we push to the main
branch.
5.1 Define the GitHub Actions Workflow
Create .github/workflows/docker-ecr-push.yml
:
name: Build and Push to ECR on: push: branches: - main # Runs on every push to main permissions: id-token: write contents: read jobs: build-and-push: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 - name: Configure AWS Credentials (OIDC) uses: aws-actions/configure-aws-credentials@v2 with: role-to-assume: arn:aws:iam::<AWS_ACCOUNT_ID>:role/GitHubActionsECRRole aws-region: us-east-1 # Change to your AWS region - name: Log in to Amazon ECR run: | aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin <AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com - name: Build and tag Docker image run: | docker build -t my-custom-grafana . docker tag my-custom-grafana:latest <AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/my-custom-grafana:latest - name: Push Docker image to Amazon ECR run: | docker push <AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/my-custom-grafana:latest
Step 6: Testing the Workflow
Once this is set up:
- Push your code to GitHub:
git add . git commit -m "Custom Grafana image with GitHub Actions and ECR" git push origin main
- Monitor the GitHub Actions workflow in your repository (
Actions
tab). - Once the image is pushed, deploy it using AWS Fargate, ECS, or Kubernetes.
Conclusion
We’ve successfully:
- Customized a standard Docker image (Grafana)
- Added custom CSS and modified configurations
- Built and tested the image locally
- Set up AWS OpenID authentication for GitHub Actions
- Automated pushing the image to AWS ECR
This approach removes the need for long-lived AWS credentials while making deployments secure and repeatable. Now, every time you push changes, your custom Docker image is automatically built and updated in AWS ECR.