Docker Github workflow with database dependency: No such container

766 views Asked by At

I am trying to figure out whats going on with Github workflows using a database dependency (MySQL actually), but I can't find any explanation or solution for my situation.

This is my workflow yaml file:

name: docker

on:
    push:
        # publish image as master=dev or on new tag
        # except on document and ci changes
        branches:
            - main
        tags:
            - '*'
        paths-ignore:
            - '**.md'
            - '.github/workflows/*yml'

    # always run tests on merge
    # except on document and ci changes
    pull_request:
        paths-ignore:
            - '**.md'
            - '.github/workflows/*yml'

jobs:
    unit_test:
        runs-on: ubuntu-latest
        if: github.event_name == 'pull_request'
        services:
            mysql:
                image: mysql:8
                ports:
                    - 3306
                env:
                    MYSQL_USER: phalcon
                    MYSQL_PASSWORD: secret
                    MYSQL_DATABASE: shop_products_test
                    MYSQL_ROOT_PASSWORD: root
                options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
        steps:
            - name: Create docker network
              run: docker network create marketplace-network
            - name: Check out Site Repository 
              uses: actions/checkout@v2
            - name: Create .env file
              run: cp .env.example .env
            - name: Replace environment variables
              run: |
                  sed -i 's/MYSQL_HOST.*/MYSQL_HOST=0.0.0.0/g' .env
                  sed -i 's/MYSQL_PORT.*/MYSQL_PORT=${{ job.services.mysql.ports[3306] }}/g' .env
            - name: Build docker image
              run: docker build -t marketplace_shop_products .
            - name: Running unit test
              run: docker-compose up products-unit-test

The purpose of this workflow is to run the unit test. But before running the unit test, there are some migrations need to be executed before to create test tables. I am using Phalcon framework, but I think it doesn't matter. What happens actually, I keep getting "Connection Refused" while I am sure that MySQL container is up and ready to be used and the IP address for MySQL container is correct, but somehow, it's not available or can't be reached by my next container "products-unit-test".

What I am about to do is to install MySQL server locally inside the container before executing the unit test, but I don't think it's the best practice. I need a separate MySQL container that unit test container connect to it in order to run migrations and do the test.

products-unit-test_1  | Copying php extensions to container ...
products-unit-test_1  | Run migrations ...
products-unit-test_1  | 
products-unit-test_1  | Phalcon DevTools (3.4.11)
products-unit-test_1  | 
products-unit-test_1  | Running migrations:
products-unit-test_1  | ERROR: SQLSTATE[HY000] [2002] Connection refused
products-unit-test_1  | 
products-unit-test_1  | PHPUnit 7.5.20 by Sebastian Bergmann and contributors.
products-unit-test_1  | 
products-unit-test_1  | Runtime:       PHP 7.3.28 with Xdebug 2.9.1
products-unit-test_1  | Configuration: /src/tests/phpunit.xml
products-unit-test_1  | 
products-unit-test_1  | ....                                                                4 / 4 (100%)
products-unit-test_1  | 
products-unit-test_1  | Time: 230 ms, Memory: 4.00 MB
products-unit-test_1  | 
products-unit-test_1  | OK (4 tests, 4 assertions)
shop_products_products-unit-test_1 exited with code 0
2

There are 2 answers

0
danblack On

Because you are passing mysql -uroot -e ... to the entry point of the container it isn't starting the daemon.

Passing the env variable MYSQL_USER, MYSQL_PASSWORD etc to the container is the correct way.

--default-authentication-plugin=mysql_native_password as a run argument will ensure its created the right way.

I can't see the error in the github services however the logs don't seem to sover the startup.

0
wajdi_jurry On

After spending many hours trying to find a solution, I came up with this one:

jobs:
    unit_test:
        runs-on: ubuntu-latest
        if: github.event_name == 'pull_request'
        services:
            mysql:
                image: mysql:8
                ports:
                    - 3306
                options: --health-cmd="mysqladmin ping"
                         --health-interval=5s
                         --health-timeout=2s
                         --health-retries=3
        steps:
            - name: Get MySQL service ID
              id: mysql-service
              run: echo "::set-output name=container-id::$(docker ps | grep -i mysql | awk '{print $1}')"
            - name: Get Github network gateway address
              id: github-network
              run: echo "::set-output name=gateway-address::$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.Gateway}}{{end}}' ${{ steps.mysql-service.outputs.container-id }})"
            - name: Check out Site Repository 
              uses: actions/checkout@v2
            - name: Create .env file
              run: cp .env.example .env
            - name: Replace environment variables
              run: |
                  sed -i 's/MYSQL_HOST.*/MYSQL_HOST=${{ steps.github-network.outputs.gateway-address }}/g' .env
                  sed -i 's/MYSQL_PORT.*/MYSQL_PORT=${{ job.services.mysql.ports[3306] }}/g' .env
            ...

First thing, I get the MySQL service ID, then I get the gateway address for the created network by Github. This way, I am sure what is the MySQL container host and port.

May help someone who searches for same problem.