How to wait for MSSQL in Docker Compose?
When you use depends_on
, docker-compose will just launch your base service with more priority and never wait for start services.
There are some useful external program that help you to wait for specific service (port), then run another service.
vishnubob/wait-for-it is one of them which blocks execution flow until your specific port(s) get ready.
Another good choice is eficode/wait-for which already prepared for docker-compose.
Example usage (according to eficode/wait-for docs)
version: '2'services: db: image: postgres:9.4 backend: build: backend # Blocks execution flow util db:5432 is ready (Or you can use localhost instead) command: sh -c './wait-for db:5432 -- npm start' depends_on: - db
-- UPDATE --
Consider you have a Python application that depend on a database like PostgreSQL, and also your application will run with this command: python app.py
As Official Docker Document said, Put vishnubob/wait-for-it
in your image (inside of your other project files like app.py
)
Now just put this lines in your docker-compose.yml
:
version: "3"services: web: build: . ports: - "80:8000" depends_on: - "db" # This command waits until `db:5432` respond (5432 is default PostgreSQL port) # then runs our application by this command: `python app.py` command: ["./wait-for-it.sh", "db:5432", "--", "python", "app.py"] db: image: postgres
Note: Don't forget to put this commands in your Dockerfile
inside your image files:
# Copy wait-for-it.sh into our imageCOPY wait-for-it.sh wait-for-it.sh# Make it executable, in LinuxRUN chmod +x wait-for-it.sh
After searching and trying many different scenarios, I was able to add waiting using the following composer file. This is for asp.net
core solution. The key is that you have to overwrite entrypoint
if it is specified in dockerfile
. Also, you need to make sure to save "wait-for-it.sh" LF as line ending instead of CRLF, otherwise you'll get the error of file not found
.
The dockerfile
should have the following (download it from here: https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh, make sure to save the file):
COPY ./wait-for-it.sh /wait-for-it.shRUN chmod +x wait-for-it.sh
docker-compose.yml
version: '3.7'services: vc-db: image: mcr.microsoft.com/mssql/server:latest ports: - "${DOCKER_SQL_PORT:-1433}:1433" expose: - 1433 environment: - ACCEPT_EULA=Y - MSSQL_PID=Express - SA_PASSWORD=v!rto_Labs! networks: - virto vc-platform-web: image: virtocommerce/platform:${DOCKER_TAG:-latest} ports: - "${DOCKER_PLATFORM_PORT:-8090}:80" environment: - ASPNETCORE_URLS=http://+ depends_on: - vc-db entrypoint: ["/wait-for-it.sh", "vc-db:1433", "-t", "120", "--", "dotnet", "VirtoCommerce.Platform.Web.dll"] networks: - virto
Create two separate dockerfiles (e.g):
- Mssql.Dockerfile
- App.Dockerfile
Set up the sequence within docker-compose.yml
Mssql.Dockerfile
FROM mcr.microsoft.com/mssql/server AS baseENV ACCEPT_EULA=YENV SA_PASSWORD=Password123COPY . .COPY ["Db/Scripts/*", "Db/Scripts/"]VOLUME ./Db:/var/opt/mssql/dataHEALTHCHECK --interval=10s --timeout=5s --start-period=10s --retries=10 \ CMD /opt/mssql-tools/bin/sqlcmd -S . -U sa -P Password123 -i Db/Scripts/SetupDb.sql || exit 1
App.Dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base WORKDIR /app EXPOSE 80 EXPOSE 443 FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build WORKDIR /src COPY ["AspNetCoreWebApplication/AspNetCoreWebApplication.csproj", "AspNetCoreWebApplication/"] COPY ["WebApp.Data.EF/WebApp.Data.EF.csproj", "WebApp.Data.EF/"] COPY ["WebApp.Service/WebApp.Service.csproj", "WebApp.Service/"] RUN dotnet restore "AspNetCoreWebApplication/AspNetCoreWebApplication.csproj" COPY . . WORKDIR "/src/AspNetCoreWebApplication" RUN dotnet build "AspNetCoreWebApplication.csproj" -c Release -o /app/build FROM build AS publish RUN dotnet publish "AspNetCoreWebApplication.csproj" -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "AspNetCoreWebApplication.dll"]
Docker-compose.yml:
version: '3.7'services: api: image: aspnetcore/mentoring_api container_name: mentoring_api build: context: . dockerfile: App.Dockerfile ports: - 8081:80 expose: - 8081 environment: ASPNETCORE_ENVIRONMENT: Development depends_on: - sqlserver sqlserver: image: aspnetcore/mentoring_db container_name: mentoring_db build: context: . dockerfile: Mssql.Dockerfile ports: - "1433:1433" expose: - 1433 environment: - ACCEPT_EULA=Y - SA_PASSWORD=Password123 volumes: - ./Db:/var/opt/mssql/data
Note:The connection string will look like: "Server=sqlserver;Database=Northwind;Trusted_Connection=False;User Id=sa;Password=Password123;MultipleActiveResultSets=true"