Search code examples
asp.netdockerdocker-composeentity-framework-core

Can We Wait for Entity Framework Migrations to Complete Before Starting a Container in Docker Compose?


I am trying to build a docker-compose.yml file to work easily in Localhost environment with asp.net + entity framework migrations + sql server.

so, my idea is to achieve a easy startup with only one docker command compose up --build However, the problem is that depends_on allows the execution of a container to continue just when the Entity Server migrations start. But, I need to wait until the entity-framework-migrations container and the populate_data_sqlserver container finish their jobs, and then start the ApiServer. I already know that docker-compose can't help here, but I am looking for a workaround and tips on how to set this up easily.

It's important to start the Sql Server, then the Migrations, then the data-pupolation and when this 3 containers are ready (1 run and the other 2 stopped) start the Api server.

Thanks for the support here.

This is my docker-compose.yml file:

version: '3.9'

services:
    sql_server:
        image: mcr.microsoft.com/azure-sql-edge
        environment:
            - "ACCEPT_EULA=Y"
            - "SA_PASSWORD=Pa$$W0rd"
        restart: always
        ports:
            - "1433:1433"
        volumes:
            - ./sql_server:/var/lib/sql_server

    entity-framework-migrations:
        build:
            context: ../
            dockerfile: Dockerfile
        depends_on:
            - sql_server
        environment:
            - ConnectionStrings__SQL=Server=sql_server,1433;Persist Security Info=False;User ID=sa;Password=Pa$$W0rd;MultipleActiveResultSets=False;Encrypt=False;TrustServerCertificate=False;;
        command: migrate

    populate_data_sqlserver:
        image: mcr.microsoft.com/mssql-tools:latest
        depends_on:
            - sql_server
            - entity-framework-migrations
            - wait_migrations
        command: /bin/bash -c '/opt/mssql-tools/bin/sqlcmd -S sql_server -U SA -P "Pa$$W0rd" -i /var/lib/sql_server/setup_db.sql -I'
        volumes:
            - ./sql_server:/var/lib/sql_server

    ApiServer:
        image: api-server-product:latest
        build:
            context: ../
            dockerfile: Dockerfile
        environment:
            - ASPNETCORE_URLS=http://+:5000
            - ConnectionStrings__SQL=Server=sql_server,1433;Persist Security Info=False;User ID=sa;Password=Pa$$W0rd;MultipleActiveResultSets=False;Encrypt=False;TrustServerCertificate=False;;
        ports:
            - "5000:5000"
        depends_on:
            - sql_server
            - entity-framework-migrations
            - populate_data_sqlserver

Solution

  • The Compose "specification" version has an extended version of depends_on: that allows it to wait for another container to run to completion. This requires version 2 of the Compose tool, built as a Docker plugin.

    So you should be able to say:

    version: '4.x'
    services:
      sql_server: { ... }
    
      entity-framework-migrations:
        depends_on:
          sql_server:
            condition: service_healthy
    
      populate_data_sqlserver:
        depends_on:
          entity-framework-migrations:
            condition: service_completed_successfully
    
      ApiServer:
        depends_on:
          populate_data_sqlserver:
            condition: service_completed_successfully
    

    You also might approach this problem by putting the migrations and seed data into an entrypoint wrapper script in the main container. That would let you get rid of the support containers, and let you use older (now-unsupported) versions of Compose. That's a more substantial change to this setup, though. How do you perform Django database migrations when using Docker-Compose? is for a different technology stack, but its answers cover almost all of the Docker-based approaches to do this.