10

I need to build docker image form the source code of the current repository, run a container, then execute some API calls. How to do that with the github action?

name: Docs Generator
on:
  pull_request:
    types: [opened]

jobs:
  pr-labeler:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
          uses: actions/checkout@v2
          with:
            ref: ${{ github.event.pull_request.head.ref }}
            repository: ${{ github.event.pull_request.head.repo.full_name }}
          
      - name: Get the version
        id: vars
        run: echo ::set-output name=tag::$(echo ${GITHUB_REF:10})
        
      - name: Build the tagged Docker image
        run: docker build . --file Dockerfile --tag service:${{steps.vars.outputs.tag}}
        
      - name: Run docker image
        docker run -v ${{ inputs.path }}:/src service:${{steps.vars.outputs.tag}}

      - name: Call API
        run: |
          curl +x http://localhost:8080/test
       
       .....

2 Answers 2

12

We can achieve this with following approach.

Advantages :

  • No need to push the intermediate docker build
  • We can build docker in one step and use it in another step without pushing it to any registry
  • We need docker/build-push-action to build the docker and addnab/docker-run-action to run the docker.

The following example shows a unit testing flow. But the concept remains same with your flow.

...
jobs:
  unittest:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3    
      - uses: docker/setup-buildx-action@v2
      - uses: docker/build-push-action@v4
        with:
          context: .
          file: "Dockerfile.test"
          tags: localpytest:latest
          load: true
          cache-from: type=gha
          cache-to: type=gha,mode=max
          push: false
      - name: Run Pytest
        uses: addnab/docker-run-action@v3
        with:
          image: localpytest:latest
          run: pytest    

  • For addnab/docker-run-action, observe the load parameter. The default value for this is false. This has to be true to use an image from one step in another step.
  • For docker/build-push-action, observe the push parameter as false. So we are not pushing it to any docker registry.
  • Github also provides docker layer caching. This helps to improve speed in later builds.
Sign up to request clarification or add additional context in comments.

Comments

4

For this purpose, you could use a combination of https://github.com/marketplace/actions/build-and-push-docker-images and https://github.com/addnab/docker-run-action

The first would build and publish a container, and the second would take this container and run your commands there.

The example is below. I don't use this setup myself but I have tested it. Replace username/container with your username and container.

name: Docker Image CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
    compile:
        name: Build and run the container
        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.DOCKERHUB_USERNAME }}
              password: ${{ secrets.DOCKERHUB_TOKEN }}
          - name: Build and push
            uses: docker/build-push-action@v2
            with:
              push: true
              tags: username/container
          - name: Check out the repo
            uses: actions/checkout@v2
          - name: Run the build process with Docker
            uses: addnab/docker-run-action@v3
            with:
                image: username/container:latest
                options: -v ${{ github.workspace }}:/data
                run: |
                    echo "Hello World"

Note that building a container is quite a long task and might deplete your Github Action limits quickly. You might consider building/publishing a container separately, or add better caching here (i.e. to rebuild it only on Dockerfile change)

Note that you need to set up DOCKERHUB_USERNAME and DOCKERHUB_TOKEN secrets.

Instead of echo "Hello World", use the commands you want to run. The repo data will be in the /data directory, for this setup.

1 Comment

If your docker run step, for example: echo "Hello World" would fail, the step would still go forward as successful, is there a way to catch the error if something fails in the container?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.