10

I start a docker container within my github action and try to access it from an action. But the action is not able to resolve the hostname. How do add my container to the same docker network as the action and let the action access it by its hostname?

steps:
  - name: Run Fuseki
    run: docker run -p 3030:3030 --name fuseki -d stain/jena-fuseki /jena-fuseki/fuseki-server --file=/staging/aksw.org.nt /aksw
  - name: curl
    uses: wei/curl@master
    with:
      args: https://fuseki:3030/aksw

The complete file is available on GitHub.

white_gecko
  • 4,808
  • 4
  • 55
  • 76

2 Answers2

9

I have the same issue in my workflows when working with a mix of services, docker actions and plain old docker commands in shell steps. At the moment, I only see two possible workarounds:

  1. Run everything on the host network. Services can publish their ports on the host. using the ports field. For example:
   services:
      redis:
        image: redis
        ports:
          - 6379:6379

In your other steps and actions you can pass the --network "host" option to docker. To access any of the containers just call localhost:port. This will work from the shell of your steps and from within the containers. It's the simplest solution. Unfortunately, you might have collisions between services and I don't really know if there is any serious security implications doing this on github hosted runners.

  1. You can start your containers in the network created by the runner using --network ${{ job.container.network }}. By passing --cidfile $CID_FILE you can store the id of the container in a file $CID_FILE. From there you can use docker inspect and output the container IP address. By doing so, even if the names of the containers don't resolve you can still connect from one container to the other using IP addresses. Here is how it can be implemented in a simple action:
    name: Docker start container
    description: Start a detached container
    
    inputs:
      image:
        description: The image to use
        required: true
      name:
        description: The container name
        required: true
      options:
        description: Additional options to pass to docker run
        required: false
        default: ''
      command:
        description: The command to run
        required: false
        default: ''
    
    outputs:
      cid:
        description: Container ID
        value: ${{ steps.info.outputs.cid }}
      address:
        description: Container ID
        value: ${{ steps.info.outputs.address }}
    
    runs:
      using: composite
      steps:
        - name: Pull
          shell: bash
          run: docker pull ${{ inputs.image }}
    
        - name: Run
          env:
            CID_FILE: ${{ inputs.name }}.cid
          shell: bash
          run: >
            docker run -d
            --name ${{ inputs.name }}
            --network host
            --cidfile $CID_FILE
            ${{ inputs.options }}
            ${{ inputs.image }}
            ${{ inputs.command }}

        - name: Info
          id: info
          shell: bash
          run: |
            export CID=$(cat $CID_FILE)
            export ADDR=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $CID)
            echo "::set-output name=cid::$CID"
            echo "::set-output name=address::$ADDR"

This is probably safer but outside the added complexity, it has one major drawback: the container addresses are not known when the job starts. It means that you cannot pass any of these IP addresses to other containers using job-wide environment variables.

ITChap
  • 4,057
  • 1
  • 21
  • 46
  • Do actions run on the host network as well? Are they able to access my "good old containers" in the first case? – white_gecko Dec 17 '20 at 22:35
  • @white_gecko sorry I should have made this clearer. Docker actions won't run in the host network but they will be able to reach containers in the host network by accessing localhost. They, themselves, won't be reachable on localhost from other containers. – ITChap Dec 18 '20 at 08:53
2

My solution is to define a custom docker network and don't use actions, but run the subsequent services as docker containers an their own. This is not very clean but works as long as GitHub does not allow me to specify a custom network of an action or document how I can make my custom container available to the actions DNS.

steps:
  - name: Create Docker Network
    run: docker network create data
  - name: Run Fuseki
    run: docker run -v ${{ github.workspace }}/.aksw-model:/staging --network data --name fuseki -d stain/jena-fuseki /jena-fuseki/fuseki-server --file=/staging/aksw.org.nt /aksw
  - name: curl
    run: docker run --rm --network data curlimages/curl:latest http://fuseki:3030/aksw

The actual and complete file is available on GitHub.

white_gecko
  • 4,808
  • 4
  • 55
  • 76