Go to Blog

Migrating a dotnet core console app to Docker

dockerdotnetcoredotnet

Before we get started, if you don't know about Docker, you should definitely have a read up about Docker.

Docker containers wrap up software and its dependencies which allows developers to build, ship and run applications anywhere.

Prerequisites

Before starting this exercise, we had a basic build plan that clones our repo and runs a dotnet publish. We had to use a linux build agent in bamboo to use specific tools (docker, gcloud, ssh, etc.)

Docker configuration files

To "dockerize" our app, we need both a Dockerfile and a docker-compose-<environment>.yml

Dockerfile

Docs

A simple text file that contains the commands a user can call to assemble an image, that can execute command-line instructions in succession

docker-compose.yml

Docs

A tool for defining and running multi-container Docker applications, across multiple isolated environments

docker-compose transformation

We need to add our image name & tag to the docker-compose file so that our build server knows what image to deploy later on

Building the Docker image

Build the my-console-app image with the branch & build number as the tag

docker build -t gcr.io/my-org/my-console-app:${bamboo.repository.git.branch}-${bamboo.buildNumber} .

Push to our docker registry

Push the image to the gcloud docker registry, so that we can pull it & use it later on

gcloud docker -- push gcr.io/my-org/my-console-app:${bamboo.repository.git.branch}-${bamboo.buildNumber}

Deployment

As we want this to run on a scheduled basis (once a day), we don't want the containter to be always running. We'll deploy it once per day, the container will auto start and execute our code & then close the container when completed

Docker swarm

Docker Swarm is a clustering and scheduling tool for Docker containers. With Swarm, developers can establish and manage a cluster of Docker nodes as a single virtual system.

Create deployment directory on our docker swarm

ssh [email protected]${bamboo.SwarmMasterIp} '[[ -d deployments/${bamboo.deploy.project} ]] || mkdir deployments/${bamboo.deploy.project}'

Deploy to docker swarm (& run the container)

Remote onto our docker swarm and download the version of the container we want to deploy

ssh -p 14122 [email protected]${bamboo.SwarmMasterIp} 'gcloud docker -- pull gcr.io/my-org/my-console-app:${bamboo.planRepository.branch}-${bamboo.buildNumber}'

(Secure) Copy the docker-compose file to our docker node

scp -P 14122 docker-compose-production.yml [email protected]${bamboo.SwarmMasterIp}:~/deployments/${bamboo.deploy.project}

Deploy our application 'stack' to the swarm using the config defined in our compose file

ssh -p 14122 [email protected]${bamboo.SwarmMasterIp} 'docker stack deploy -c ~/deployments/${bamboo.deploy.project}/docker-compose-production.yml myorg-prod --with-registry-auth'

Issues & concerns

The main issues I'd encountered while doing the above were:

  1. Unsure that correct files were copied to the container A quick resolution for this was to add the following line to our Dockerfile: RUN ls or to view every file on the container: RUN find "$PWD"
  2. Incorrect RUN command A hard one to find but I got there eventually - as I'd copied the RUN command from the microsoft docs, I assumed I was having problems elsewhere - it turns out that our container didn't like the RUN ["dotnet", "my-app.dll"] command, as a ./ was missing at the start of our dll path!
  3. Using the correct image For most popular docker images, there are many different tags which are build differently with different features in the container. We could have used the aspnet image as we do in all of our other docker applications (which are all APIs) but in our case, it doesn't make sense as we don't need all of the tools that are included in the image. We swapped to use the dotnet-runtime image (which is almost 50% smaller), meaning a faster pipeline (i.e. building, pushing and pulling the image)

Debugging

To view the logs of your container while / after it has ran, portainer is a useful tool that lets you view service & container logs. If this tool isn't available, you can do this directly by ssh'ing onto the swarm and viewing service logs:

ssh [email protected]$DockerSwarmNode
docker service logs <serviceID>

You can find the serviceID from running either of the following:

docker ps
docker ps | grep my-app

Remoting onto containers

Not applicable for our scenario but useful for long running tasks or persisting containers such as API's.

docker exec -t -i <containerID> /bin/bash

ls
Enjoy my content? Want to buy me some snacks and support this hungry developer?
Buy Me A Coffee
Go to Blog
© Steve Baker 2021, Built using Gatsby. Last updated: 1/31/2021