Episode 4 - JSON API using ASP.NET Core, Docker & MongoDB - Docker Part II Docker Compose
Tags: blog, howto, aspnetcore, beginners
Published: 2018-12-31 11:12:22

---
title: Episode 4 - JSON API using ASP.NET Core, Docker & MongoDB - Docker Part II Docker Compose
published: false
tags: blog,how-to,aspnetcore,beginners
canonical_url: https://garfbradaz.github.io/blog/2018/12/31/Episode-4-JSON-API-ASP.NET-Core-Docker-Compose.html
cover_image: https://thepracticaldev.s3.amazonaws.com/i/abi2arzus9vlb8s6rp7p.PNG
series: ASP.NET Core Web API Episodes
published: true
---

## Previously on Dcoding

In [Episode 3](https://dev.to/garfbradaz/episode-2---json-api-using-aspnet-core-docker--mongodb-docker-part-i-dockerfiles-2o8i) I set up our Dockerfiles for creating our _Docker Images_ for our BookStore app. This will allow us to rapidly test our application as we move forward in later Episodes. Today’s episode is **Docker Part 2: Docking Compose**. <!--more-->

## What is Docker Compose?

The [official documentation](https://docs.docker.com/compose/) a good explanation:

> Compose is a tool for defining and running multi-container Docker applications.

Docker compose allows you to define your _services_ you need to build and run a full scale application. Think about it, it is not just your application you need. Depending on the type of application you may want:

- Database of some sort.

- Load Balancer.

- Web Server.

- Other applications / APIs.

You may even want to run your unit/integration testing during your Continuous Integration pipeline (CI). You could do that with Docker and Compose.

## BookStore.WebApi Set up

If we take a look at our application for the _BookStore.WebApi_, we can see the following:

![architecture diagram](https://garfbradaz.github.io/assets/img/posts/docker-arch.png)

As you can see from my quickly drawn up diagram (used [Microsoft Whiteboard](https://www.microsoft.com/en-gb/p/microsoft-whiteboard/9mspc6mp8fm4?activetab=pivot:overviewtab)), we have two _services_ running in containers, 1 for the application and the other for the database (_MongoDB_), so we can compose these together using `docker-compose`.

## docker-compose.dev.yml

So in [Episode 2](https://dev.to/garfbradaz/episode-2-json-api-dotnet-core-docker-project-structure-3i0c) we set up the Project Structure, so change directory to the `./docker` directory.

```
.
    ├── src
    | ├── api
    | |
    | ├── BookStore.WebApi.csproj
    | ├── Dockerfile
    ├── tests
    | ├── integration
    | ├── unit
    | ├── BookStore.Tests.csproj
    ├── docker
```

Within that directory, you should have two empty YAML files:

- **docker-compose.dev.yml**
- **docker-compose.yml**

We are concentrating on a _Development_ environment first, so add the following to `docker-compose.dev.yml`. These files help us define the shape of our services and the dependancies they have:

```
version: "3"
services:
  webapi:
    image: garfbradaz/bookstoreapi:develop
    container_name: webapi_tutorial_debug
    build:
      args:
        buildconfig: Debug
      context: ../src/api
      dockerfile: Dockerfile
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://+:5003
    ports:
      - "5003:5003"
    depends_on:
      - mongodb
  mongodb:
    image: mongo:latest
    container_name: mongodb
    ports:
      - "27017:27017"
```

And also, just add the following line to `docker-compose.yml` file so that when we run `docker-compose up` it doesn’t fail:

```
version: "3"
```

As in **Episode 3** lets break this _YAML_ file down now and what we are declaring. These files are _YAML_ and following the normal _YAML_ syntax rules around indenting etc.

### `version:`

This is really important. The currently released version (as of December 2018) is **3(.7)**. You only have to include the whole number within the `version` number field within the YAML file. Each _major_ upgrade (from 1.x, to 2.x, to 3.x) brings about possible breaking changes, including syntax changes to the YAML structure itself.

Also the version of Compose relates to the version of the released _Docker Engine_ so have a good read of the [Compatibility Matrix](https://docs.docker.com/compose/compose-file/compose-versioning/#compatibility-matrix), but usually you pick the latest version.

### `services:`

[Docker services](https://docs.docker.com/get-started/part3/) is where you define each application. So we have two services defined:

- `webapi:` which is our ASP.NET Core _BookStore.WebApi_ application.
- `mongodb:` which is the back-end data store, _MongoDB_.

### `image:`

Each service has an `image` defined. Mongo’s [`mongo:latest`](https://hub.docker.com/_/mongo) will be pulled directly from _hub.docker.com_.

Our own will be built locally for now (until we publish it later) and its simply called `garfbradaz/bookstoreapi:develop`. Note the _tag_ of **develop**. We now have denoted our debug image, and we can add things like symbols etc for debugging purposes.

### `container_name:`

This is just a nice friendly name for our container. You can see the name when you run `docker ps` after you have run a container.

## Run your applications

Docker compose has a command `docker compose up`, which allows you to (re)build, (re)create and attach containers for the service. You run the command using the following (make sure you are in the `./docker` directory):

```
docker-compose -f docker-compose.dev.yml up -d --build
```

This command overrides the file (`-f`) to `docker-compose.dev.yml` and runs `up`. The containers will run in detached mode (`-d`) and run in the background. We will also (re)build the images (`--build`). Because we have a `build` section in our `docker-compose.dev.yml` file for our code those values will be used. We set the context (`../src/api`) which is the relative directory to the source code we are building (Relative to the `./docker` directory), plus tell `docker-compose` the Dockerfile name.

We also send in some `args` _into_ the Dockerfile. Currently we ignore these, but we will be coming back to them later in this post.

Lastly we set some `environment` variables for our application/ASP.NET Core to use. Specifically around setting up a `Development` environment and HTTP URLs.

**Note:** If we dont set these, our application will try and use HTTPS because that is the default now (which is a good thing). Because we haven’t set any self-signed developer certificates up yet this will become a bit of a pain. We will do it, but to get up and running, we are switching off HTTPS for now.

We also pull down a **MongoDB** image and start a new database, listening on port 27017. This is the standard port mapping for MongoDB.

This command will also create a default network for your applications to live in. Normally named after the directory `docker-compose` is run with a postfix of **default**. So mine is `docker_default`.

## Check the containers are running

You can now run a `docker ps` on your commandline of choice. You should see your `webapi_tutorial_debug` and `mongodb` ( **Hint:** `container_name` you set in the `docker-compose.dev.yml` file).

![docker ps](https://garfbradaz.github.io/assets/img/posts/docker-ps.png)

## Stop containers

When you have finished you can clear up your containers by running the following, which will stop and remove the containers networks created for this service:

```
docker-compose -f docker-compose.dev.yml down
```

## Powershell Scripts (Optional)

I have created two powershell scripts that automate this. You just need to run them in the root of the project:

### Run containers

```
.\run.ps1
```

### Close and clean containers

```
.\clean.ps1
```

Powershell Core is now cross platform as well so you can install Powershell Core and use these scripts on Mac and Linux boxes if you wish.

## Debug Arguments

Previously I mentioned we set a `arg` called `buildconfig` to `Debug`. We haven’t used this so far. But we will now. I use this to build a debug version of our ASP.NET Core _BookStore.WebApi_ app, so we can debug into the container using _vsdbg_.

Have a read of my article [Debug .NET Core in Docker](https://dev.to/garfbradaz/debug-dotnet-core-in-docker-5c66) about what this is. For this article, change directory to `./src/api` and make sure your `Dockerfile` looks like this:

```
FROM microsoft/dotnet:2.2-sdk AS build-env
ARG buildconfig
WORKDIR /app
COPY BookStore.WebApi.csproj .
COPY . .
RUN env
RUN if ["${buildconfig}" = "Debug"]; then \
        dotnet publish -o /publish -c Debug; \
    else \
        dotnet publish -o /publish -c Release; \
    fi 

FROM microsoft/dotnet:2.2-aspnetcore-runtime AS runtime-env
ARG buildconfig
ENV DEBIAN_FRONTEND noninteractive
WORKDIR /publish
COPY --from=build-env /publish .
RUN if ["${buildconfig}" = "Debug"]; then \
        apt-get update && \
        apt-get install -y --no-install-recommends apt-utils && \
        apt-get install curl unzip procps mongodb -y && \
        curl -sSL https://aka.ms/getvsdbgsh | bash /dev/stdin -v latest -l /publish/vsdbg; \
     else \ 
        echo "*Whistling*"; \
    fi 
ENV DEBIAN_FRONTEND teletype
ENTRYPOINT ["dotnet","BookStore.WebApi.dll"]
```

## Next time

That’s it for today. Remember all code is on [Github](https://github.com/garfbradaz/webapi-episodes/tree/master/episode-4) if you want it.

Now we have our architecture spun up and ready, we can start building some ASP.NET Core code (using C#) to start creating our Models for our _BookStore.WebApi_. We will also start creating some unit tests and creating the shape of our API.