Github actions docker build "uses" vs manual - docker

tonight I stumbled across something I found really strange and I can't find a good answer to it. I'm building a docker image on my Raspberry Pi (where this is a dashboard acting as a home server). I'm still fairly new to using Github actions, but I use a Gitlab/Jenkins setup at work.
With the exact same code, building and pushing the docker image with the following took around 10 minutes. I ran into some further issues and it timed out, so I thought of building it manually as opposed to the "uses: docker/build-push-action" method.
I'm struggling to understand what's happening under the hood and why there is such a massive performance difference. Is there a reason why the "using" method might be preferred?
Raspberry Pi B3+, Ubuntu arm64
~10 Minutes. Sample run: https://github.com/helblingjoel/piserver/actions/runs/2332932188
- name: Login to DockerHub
uses: docker/login-action#v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action#v2
- name: Build and push
uses: docker/build-push-action#v2
with:
push: true
tags: helblingjoel/piserver:${{ steps.date.outputs.date }}
cache-from: type=registry,ref=helblingjoel/piserver:buildcache
cache-to: type=registry,ref=helblingjoel/piserver:buildcache,mode=max
~3 minutes. Sample run: https://github.com/helblingjoel/piserver/actions/runs/2334507767
- name: Login to DockerHub
uses: docker/login-action#v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.
- name: Build docker image
run: docker build -t helblingjoel/piserver:${{ steps.date.outputs.date }} .
- name: Push docker image
run: docker push helblingjoel/piserver:${{ steps.date.outputs.date }}
The Dockerfile used for those was identical.
Thank you in advance.

Related

How to pass a variable from GitHub action to Docker container?

When I push a commit with a tag, a docker container is automatically built by the docker/build-push-action#v1 GitHub Actions. The tag indicates the version number, which I want to show in the application.
Here is my workflow:
- name: Push to Docker Hub - develop
uses: docker/build-push-action#v1
with:
repository: my_repo/my_image
path: frontend/
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
tags: develop
args: SOFTWARE_VERSION=${{ steps.vars.outputs.tag }}
At that moment the variable SOFTWARE_VERSION should be available in the Dockerfile, is that right?
In my Dockerfile I set:
ARG SOFTWARE_VERSION
ENV SOFTWARE_VERSION ${SOFTWARE_VERSION}
Inside the container, the variable has an empty value. How to do it properly?
I don't know if it matters, but I run the container using docker-compose.
You are using args to pass the arguments.
However, the #v1 of https://github.com/docker/build-push-action offers build_args and #v3 build-args.
You should choose accordingly for the version that you need to use. IMO, you should go for the latest one.
Go to your Settings->Secrets and Variables
Add two Secrets
DOCKERHUB_USERNAME your username on Dockerhub
DOCKERHUB_TOKEN this is the token,you can get it from DockerHub
You must add this to precede Build and Push
— name: Login to DockerHub
if: GitHub.event_name != 'pull_request'
uses: docker/login-action#v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

Tag new Docker image push automatically for CI/CD deployment in Github Action

I want to be able to run a Github action that would build, automatically & uniquely tag and push an image to Docker hub.
I want it to also be that another Github action that deploys to the server will automatically know the image's tag and adds it to the image name to pull that specific image automatically.
Try the Publish Docker GitHub Action.
Example workflow that will trigger on new GH Release creation and will use the GH release version for tagging the Docker image:
name: Publish to Registry
on:
release:
types: [published]
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v3
- id: pre-step
shell: bash
run: echo "release-version=$(echo ${GITHUB_REF:10})" >> $GITHUB_OUTPUT
- name: Publish to Registry
uses: elgohr/Publish-Docker-Github-Action#v5
with:
name: myDocker/repository
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
tags: "latest,${{ steps.pre-step.outputs.release-version }}"
Also, you can use tag_names when you want to push tags/release by their git name (e.g. refs/tags/MY_TAG_NAME):
with:
name: myDocker/repository
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
tag_names: true
For more details visit the Usage section.

Refer to Docker image variable name in Github Action

I'm very new with github actions, caprover and docker images so I might be asking very stupid questions, sorry if it is the case. I searched for a good amount of time and could not understand it by myself...
So, I'm trying to deploy to caprover a docker image built just before in my github action. Please see below my .yml file:
name: Docker Image CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v3
- name: Build the Docker image
run: docker build . --file Dockerfile --tag my-image-name:latest
- name: Print image names
run: docker images -q my-image-name
- name: Deploy image
uses: floms/action-caprover#v1
with:
host: '${{ secrets.CAPROVER_SERVER }}'
password: '${{ secrets.CAPROVER_PASSWORD }}'
app: '${{ secrets.APP_NAME }}'
image: my-image-name:latest
The Build the Docker image step was successful, but the Deploy image one was not. The error message I got was:
Build started for ***
An explicit image name was provided (my-image-name:latest). Therefore, no build process is needed.
Pulling this image: my-image-name:latest This process might take a few minutes.
Build has failed!
----------------------
Deploy failed!
Error: (HTTP code 404) unexpected - pull access denied for my-image-name, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
Based on the error message, I believe I do not give the correct image name to the floms/action-caprover#v1 action. It is why I created step 2 Print image names to try and understand better what is the real name of the image created. I tried several solutions for the field name image, but all resulted in an error...
Thanks for the all the help you could provide!
To make sure your CapRover instance is able to pull the image from your github docker registry, it needs to be registered on your CapRover instance.
TLDR: I don't see a publish step (for your docker image) in your GitHub Actions configuration. If you want to use the image name to push it to CapRover you will need to publish it to a registry, whether it is GitHub's Container Registry, Nexus registry, or any other registry.
To do that in your CapRover instance, you need to go into Cluster > Docker Registry Configuration > Add Remote Registry. Then you will proceed to enter the configuration for your GitHub Container Registry. Typically you will need a Personal Access Token to allow CapRover to communicate with GitHub instead of using your password.
Docker Registry Configuration
Remote Registry Configuration
Docker Registry Configuration - Remote Registry Configured
Thanks Yoel Nunez for pointing I should deploy to the registry before trying to publish to caprover.
I followed the doc on github and finally managed to publish to caprover using a github action. Below is the .yml file that worked perfectly.
name: Publish to caprover
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout#v3
- name: Log in to the Container registry
uses: docker/login-action#v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.PAT }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action#v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push
uses: docker/build-push-action#v3
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Deploy image
uses: floms/action-caprover#v1
with:
host: '${{ secrets.CAPROVER_SERVER }}'
password: '${{ secrets.CAPROVER_PASSWORD }}'
app: '${{ secrets.APP_NAME }}'
image: ${{ steps.meta.outputs.tags }}

How to correctly push a Docker image using Github actions

I am setting up a Github action to push a Docker image to Docker Hub following Github official README.md for docker/build-push-action#v2.
This is my action inside directory .github/workflows/
name: Publish Docker image
on:
push:
branches: master
jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
steps:
-
name: Set up QEMU
uses: docker/setup-qemu-action#v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action#v1
-
name: Login to DockerHub
uses: docker/login-action#v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
-
name: Build and push
id: docker_build
uses: docker/build-push-action#v2
with:
push: true
tags: user/app:latest
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
Having tested the action worked in my fork branch I then merged the branch to the main repo. To my surprise the login step failed showing the following error inside Github actions log
Run docker/login-action#v1
with:
logout: true
Error: Username and password required
At first I thought I could have wrongly defined (or even not defined) the secrets inside the main repo but after a request with octokit I found out that they are there
{
total_count: 2,
secrets: [
{
name: 'DOCKER_PASSWORD',
created_at: '2020-11-04T15:28:55Z',
updated_at: '2020-11-16T13:11:27Z'
},
{
name: 'DOCKER_USERNAME',
created_at: '2020-11-04T15:28:55Z',
updated_at: '2020-11-16T13:11:27Z'
}
]
}
I guess that docker/login-action#v1 is not using username and password provided after the with: keyword. I am very puzzled by this as it did work on my fork branch and do not understand why with: is sending the keyword logout: true instead which I did not set.
Does someone have more insight into this ?
Could you check that in the repository's settings the secrets are there like this:
Also, when you say
Having tested the action worked in my fork branch I then merged the branch to the main repo.
does this mean the main repo is also yours?
Because secrets don't transfer between repos. If you've forked another user's repository and want to contribute workflow changes requiring secrets, the main repo's owner(s) will have to add secrets with the same name.
Additionally, secrets aren't used in Pull Requests workflow runs. Hence you'll only see if it's working after the changes have been merged into the repository.
I have run into the same issue please check where you are giving your secret, now GitHub has two types of secrets, you should use Actions as shown in the image. If you use depependabot.

Github Actions: Push docker image build by gradle task

For building images of my current project, I use the gradle task bootBuildImage. This task creates a OCI image using Cloud Native Buildpacks.
- name: Build image with Gradle
run: ./gradlew bootBuildImage
With the next step I'm trying to push this docker image to my private GitHub registry using build-push-action.
- name: Push image to Registry
uses: docker/build-push-action#v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
registry: docker.pkg.github.com
repository: sullrich84/wettkampfdb-backend
tags: latest
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
As I can tell from the logs, the problem with this step is that it seems to rely on a Dockerfile located in the workspaces root directory which does not exist.
unable to prepare context: unable to evaluate symlinks in Dockerfile path:
lstat /github/workspace/Dockerfile: no such file or directory
Is it possible to push the image created via bootBuildImage to my private GitHub registry without using/creating a dedicated Dockerfile?
If you are just looking for something to deal with docker push, you can just use the native docker command to do it.
Something like this.
- name: run docker push
run: |
#docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
#docker push $BUILD_TAG
#docker push $LATEST_TAG
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
The github-action you are using is not for pushing an image you define by repository and tag but rahter build and push https://github.com/docker/build-push-action#build-push-action
Builds and pushes Docker images and will log in to a Docker registry if required.
Specifically this is also related to https://github.com/docker/build-push-action/issues/17 - so just building without pushing is possible, not vice versa.
This github action does yet not allow just pushing.
This is for now very common for a lot of CI/CD solutions, where build and push are one task.
I use publishRegistry option of gradle bootBuildImage.
Set parameter in your build.gradle (below is gradle.kts)
tasks.bootBuildImage {
imageName = "${imageName}:${project.version}"
isPublish = true
docker {
publishRegistry {
url = dockerUrl
username = dockerUsername
password = dockerPassword
}
}
}
check this document

Resources