.NET Core continuous integration and deployment with Gitlab, Docker, Kubernetes and Google Cloud
February 01, 2017
Over the past few months I’ve put Roadkill on hold in my free time, to get some .NET core projects working inside Docker. They’re mostly sandbox websites for exploring the tech stack, and are hosted privately in Gitlab. Gitlab gives you a decent CI server for free, which works really well with CI and deployment of .NET core apps (both websites and console apps).
How the build works
As .NET core runs in Linux, you no longer have to worry about spinning up an over-powered Windows server. What’s more you can do it all inside a Docker container. I plan to do a series of posts on my learnings with .NET core and Kubernetes, in the meantime below is the YAML build definition build I used. It does the following:
- Build and publish (publish is just creating a clean bin folder with assets) the .NET Core app in release mode
- Build the Docker image in the repository:
docker build -t gcr.io/my-kube-project/...
- The tag I use for each Docker image is the short Git commit ID.
- Finally push to the Google Cloud Docker registry.
One final step you could easily add is performing a kubectl edit deployments/...
to update the Docker image to the latest tag, but it’s not in the YAML build definition file.
What does the app do?
The app has a website, and then a Google Cloud Pub/Sub part that is used for updating data that the website uses periodically. The Pub/Sub part is a publisher and a poller-based subscriber. I tried using push but Google Cloud had a habit of denial of servicing my endpoint, even with throttling enabled inside Nginx.
All three bits are Docker containers running as seperate pods inside a Kubernetes cluster.
How can I change the file so it works with Bitbucket Pipelines/Travis/Appveyor/CI-service XYZ
You could convert it really easily to another build service YAML format. Appveyor wouldn’t make much sense, but other services would be trivial to do.
Source
# http://docs.gitlab.com/ce/ci/docker/using_docker_build.html#using-the-gitlab-container-registry | |
# The docker tag is the first 6 letters of the Git commit id | |
job_build_dotnet: | |
stage: build | |
image: microsoft/dotnet:latest | |
script: | |
- dotnet restore | |
- dotnet publish src/MyProject.Web -c Release | |
artifacts: | |
expire_in: 12 hrs | |
paths: | |
- src/MyProject.Web/bin/Release/netcoreapp1.1/publish/ | |
job_build_docker: | |
stage: deploy | |
image: docker:latest | |
services: | |
- docker:dind | |
script: | |
- export DOCKER_VERSION=$(echo "$CI_BUILD_REF" | cut -c 1-6) | |
- echo "$GOOGLE_AUTH_JSON" > google-cloud.json | |
- cd src/MyProject.Web && docker build -t gcr.io/my-kube-project/MyProject-web:$DOCKER_VERSION . | |
- cd ../../ && docker login -e 1234@5678.com -u _json_key -p "$(cat google-cloud.json)" https://gcr.io | |
- docker push gcr.io/my-kube-project/MyProject-web:$DOCKER_VERSION | |
dependencies: | |
- job_build_dotnet |
I'm Chris Small, a software engineer working in London. This is my tech blog. Find out more about me via Github, Stackoverflow, Resume