Search code examples
github-actionsmicronaut

GitHub Actions: Is it possible to call the runner host from a Docker container?


In the GitHub Actions workflow below I execute a Gradle build that runs integration tests against a Micronaut application. This application is dependent on

  • a MariaDB database
  • and a security/image:0.1.15
jobs:
  build-test:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        java: [ '15' ]

    services:
      tempoapp-db:
        image: mariadb:10.4.15
        ports:
          - 3306:3306
        env:
          MYSQL_ROOT_PASSWORD: foo
          MYSQL_DATABASE: xoxo
          MYSQL_USER: bar
          MYSQL_PASSWORD: foobar

      security:
        image: security/image:0.1.15
        env:
          JAVA_TOOL_OPTIONS: "-Dcallback.url=http://<what to place here?>:8090"
        credentials:
          username: ${{ secrets.PACKAGES_USER }}
          password: ${{ secrets.PACKAGES_TOKEN }}
        ports:
          - 6000:8080

    steps:
      - name: Check out repository
        uses: actions/checkout@v2

      - name: Set up JDK
        uses: actions/setup-java@v1
        with:
          java-version: ${{ matrix.java }}

      - name: Build and test the application
        run: ./gradlew -s check publishToMavenLocal dockerPrepare

Within the integration test phase the security/image:0.1.15 Docker container is required to access the Micronaut application running on the Docker host. In my Docker Desktop environment I usually use the hostname host.docker.internal to get access from a container to the host. This does not seem to work on GitHub Actions since I get the following error

io.micronaut.http.client.exceptions.HttpClientException: Connect Error: host.docker.internal: Name does not resolve
    at io.micronaut.http.client.netty.DefaultHttpClient.lambda$null$34(DefaultHttpClient.java:1119)
    at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:578)
    at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:552)
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:491)
    at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:616)

Is there a way to get an IP address or hostname of the host?

security:
  image: security/image:0.1.15
  env:
    JAVA_TOOL_OPTIONS: "-Dcallback.url=http://<what to place here?>:8090"

Solution

  • TL;DR: Use 172.17.0.1 to access your Docker host.

    I have managed to solve my issue. This answer gave me a hint into the right direction (https://stackoverflow.com/a/60740997/960875)

    AFAIK, in the case of Docker for Linux (standard distribution), the IP address of the host will always be 172.17.0.1 (on the main network of docker, see comments to learn more).

    In order to verify this I added an additional workflow step that starts an Alpine Linux container and prints the Docker host ip (thanks to @Nek)

    1. Run an Alpine Docker
    2. Updates dependencies (quietly)
    3. Install iproute2 package (quietly)
    4. Shows (nicely) the ip of the host
    5. Removes the docker (thanks to --rm arg)
    - name: Find Docker Host IP
      uses: addnab/docker-run-action@v1
      with:
        image: alpine:latest
        run: apk update > /dev/null && apk add iproute2 > /dev/null && ip -4 route show default | cut -d' ' -f3
    

    As you can see in the screenshot below the IP is 172.17.0.1.

    enter image description here

    So I added the IP to the JAVA_TOOL_OPTIONS env variable of my security container and everything works fine.

    jobs:
      build-test:
    
        runs-on: ubuntu-latest
        strategy:
          matrix:
            java: [ '15' ]
    
        services:
          tempoapp-db:
            image: mariadb:10.4.15
            ports:
              - 3306:3306
            env:
              MYSQL_ROOT_PASSWORD: foo
              MYSQL_DATABASE: xoxo
              MYSQL_USER: bar
              MYSQL_PASSWORD: foobar
    
          security:
            image: security/image:0.1.15
            env:
              JAVA_TOOL_OPTIONS: "-Dcallback.url=http://172.17.0.1:8090"
            credentials:
              username: ${{ secrets.PACKAGES_USER }}
              password: ${{ secrets.PACKAGES_TOKEN }}
            ports:
              - 6000:8080
    
        steps:
          - name: Check out repository
            uses: actions/checkout@v2
    
          - name: Set up JDK
            uses: actions/setup-java@v1
            with:
              java-version: ${{ matrix.java }}
    
          - name: Build and test the application
            run: ./gradlew -s check publishToMavenLocal dockerPrepare