2

I am trying to construct ci process to build, test and publish my .NET Core app using Docker-Compose and bash scripts.

I have UnitTests, IntegrationTests and XApi projects in a folder and have created DockerFile and docker-compose.yml like below.

IntegrationTests are dependent to mongointegration, so I added links and depends_on attributes to testandpublish service in docker-compose.yml.

When I try to docker-compose up or docker-compose up testandpublish, it fails to connect mongo. (DockerFile - step 10), mongo service has not been started yet (Don't understand why)

In step 10, if I change RUN to CMD, it can connect to mongo, docker-compose works fine. But this time I cannot detect tests are failed or succeed in my sh script, because now it does not break docker-compose up command..

My question is: Why docker compose does not start service mongointegration? And if it is impossible, how can I understand that service testandpublish failed? Thanks.

Structure:

XProject
  -src
    -Tests
      -UnitTests
      -IntegrationTests
    -Dockerfile
    -docker-compose.yml
    -XApi

My Dockerfile content is (I have added line numbers to explain problem here):

1.FROM microsoft/dotnet:1.1.0-sdk-projectjson
2.COPY . /app
3.WORKDIR /app/src/Tests/UnitTests
4.RUN ["dotnet", "restore"]
5.RUN ["dotnet", "build"]
6.RUN ["dotnet", "test"]
7.WORKDIR /app/src/Tests/IntegrationTests
8.RUN ["dotnet", "restore"]
9.RUN ["dotnet", "build"]
10.RUN ["dotnet", "test"]
11.WORKDIR /app/src/XApi
12.RUN ["dotnet", "restore"]
13.RUN ["dotnet", "build"]
14.CMD ["dotnet", "publish", "-c", "Release", "-o", "publish"]

and my docker-compose.yml

version: "3"
services:
  testandpublish:
    build: .
    links:
      - mongointegration
    depends_on:
      - mongointegration
  mongointegration:
    image: mongo
    ports: 
      - "27017:27017"
skynyrd
  • 942
  • 4
  • 14
  • 34

2 Answers2

4

The image build phase and the container run phase are two very seperate steps in docker-compose.

Build and Run Differences

The build phase creates each of the image layers from the steps in the Dockerfile. Each happens in standalone containers. None of your service config, apart from the build: stanza specific to a services build, is available during the build.

Once the image is built, it can be run as a container with the rest of your docker-compose service config.

Instead of running tests in your Dockerfile, you could create a script to use as the CMD that runs all your test steps in the container.

#!/bin/sh
set -uex
cd /app/src/Tests/UnitTests
dotnet restore
dotnet build
dotnet test
cd /app/src/Tests/IntegrationTests
dotnet restore
dotnet build
dotnet test"
cd /app/src/XApi
dotnet restore
dotnet build
dotnet publish -c Release -o publish

If the microsoft/dotnet:1.1.0-sdk-projectjson image is Windows based you might need to convert this to the equivalent CMD or PS commands.

Container Dependencies

depends_on doesn't work quite as well as most people assume it will. In it's simple form, depends_on only waits for the container to launch before moving onto starting the dependent container. It's not smart enough to wait for the process inside the container be ready. Proper dependencies can be done with a healthcheck and a condition.

services:
  testandpublish:
    build: .
    links:
      - mongointegration
    depends_on:
      mongointegration:
        condition: service_healthy
  mongointegration:
    image: mongo
    ports:
      - "27017:27017"
    healthcheck:
      test: ["CMD", "docker-healthcheck"]
      interval: 30s
      timeout: s
      retries: 3

Using the Docker health check script, after it's been copied into the container via a Dockerfile.

#!/bin/bash
set -eo pipefail

host="$(hostname --ip-address || echo '127.0.0.1')"

if mongo --quiet "$host/test" --eval 'quit(db.runCommand({ ping: 1 }).ok ? 0 : 1)'; then
    exit 0
fi

exit 1
Matt
  • 68,711
  • 7
  • 155
  • 158
2

RUN steps are executed when Docker builds the image and no containers are available yet. Instead CMD step is executed on the run time and Docker Compose has already started depending mongointegration container.

Lauri
  • 4,336
  • 3
  • 18
  • 18
  • Thanks for the process explanation. How I detect `testandpublish` service failed in the bash script then? Because using `CMD` , exit status code is still 0 (success) even tests are failed. – skynyrd Mar 07 '17 at 09:39