Welcome to the twenty-third episode of my course “Becoming a software developer” in which we will focus on the vast topic of DevOps which is all about building, testing and deploying the application. And we will use Docker to help with the overall process.
All of the materials including videos and sample projects can be downloaded from here.
The source code repository is being hosted on GitHub.
Scope
- Publishing
- Docker
- Deployment
- Automation
Abstract
Publishing
When we want to run our application in a proper manner, we should not really use dotnet run and run the app based on the provided source code written in C#. Instead, we should only use the assemblies compiled into the .dll files and then execute dotnet application_name.dll which will run the actual application that was already compiled, not the project with its source code. This can be done by running dotnet publish -c Release where the -c defines the configuration that should be used. We want to use Release so that the compiler can include some optimizations for this environment in order to ensure that our application will be truly prepared for the production mode.
Docker
Docker is the most popular engine for running the applications within so-called containers, although the containers itself have been used since the 70s. You can read about the differences between virtual machines and containers, the important part is that container is very lightweight, runs on top of the current operating system (e.g. Windows or Linux), has its own and separate environment and most importantly it will behave in the same way as on our development machine, which means that we can be certain that regardless of the infrastructure, our application will work and behave as expected. Below is the sample Dockerfile for the .NET Core applications:
1 2 3 4 5 6 |
FROM microsoft/dotnet:runtime WORKDIR /dotnetapp COPY ./bin/Docker . ENV ASPNETCORE_URLS http://*:5000 ENV ASPNETCORE_ENVIRONMENT docker ENTRYPOINT dotnet Passenger.Api.dll |
We can build such image and run it by using the following commands:
1 2 |
docker build -t passenger-api . docker run -d -p 5000:5000 passenger-api |
We can also use the Docker Compose to define the whole system that can be built with many different services (application, databases etc).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
version: "2" services: api: image: spetz/passenger-api links: - mongo - mssql ports: - '5000:5000' mongo: image: mongo volumes: - ./data/db:/data/db ports: - '27017:27017' mssql: image: microsoft/mssql-server-linux environment: ACCEPT_EULA: Y SA_PASSWORD: "Abcd1234!" ports: - "1433:1433" |
And run it simply by typing docker-compose up command. Finally, we can publish our own Docker image to the registry e.g. Docker Hub, by creating an account here, adding a new repository (e.g. passenger-api) and then running the following commands:
docker login
docker tag passenger.api spetz/passenger.api
docker push spetz/passenger.api
Deployment
In this episode, I did deploy the application to the virtual machine based on Ubuntu Server running in the Digital Ocean cloud. I logged in to the VM by typing: ssh root@46.101.203.190 and then executed the following commands:
1 2 3 4 |
apt update apt install docker.io apt install docker-compose apt install nginx |
Then, we could edit the Nginx configuration under the /etc/nginx/sites-enabled directory simply by editing the default file:
1 2 3 4 5 6 7 8 9 10 11 |
server { listen 80; location / { proxy_pass http://localhost:5000; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } } |
Eventually, I did restart the Nginx with service nginx restart command, executed the docker-compose command up and our application was available under the http://46.101.203.190 URL.
Automation
Is it possible to somehow automate this process of building, testing, publishing and deploying the application? Of course, and this is where tools like build servers come in handy. There are many of them and you can browse my previous posts where I did describe how to make use of such services. Here, I chose the Travis CI which is a really cool build server and its free for the open source projects. Just sign in using the GitHub account, mark the selected repository integration, and place the .travis.yml file in the root folder of the solution:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
language: csharp dist: trusty sudo: required mono: none dotnet: 1.0.1 branches: only: - master - develop before_script: - chmod -R a+x scripts script: - ./scripts/travis-build.sh - ./scripts/test.sh after_success: - ./scripts/travis-success.sh notifications: email: on_success: never on_failure: always |
The actual content of the build scripts can be found in the project repository, just keep in mind that you could also use the pure bash commands instead.
Next
In the next episode, which will be the final one, we will do something special :).
Pingback: Dew Drop - July 31, 2017 (#2531) - Morning Dew
Awesome material I must to say, little bit oposite my normal activity but those are things that are worth to know. Thank you, I will wisit you soon again. Regards
Witaj Piotrze,
Kiedy planujesz wrzucić ostatni odcinek ? 🙂 I masz jakieś ramy czasowe odnośnie jwt i refresh token’a ?
Ps. Świetna robota z każdym kursem i postem na blogu 🙂 Planujesz ogólnie aktywizacje mocniejsza na YT ? Np jakaś seria kolejna niekonieczni cały kurs ale seria zwykła która by była systematycznie prowadzona ? 🙂
Pozdrawiam Damian.
Cześć, dzięki, ostatni odcinek najwcześniej w nadchodzącym tygodniu, nie wiem jeszcze kiedy wrzucę materiał o odświeżaniu JWT, bo mam trochę zaległości.
Odnośnie YT to mam sporo pomysłów i prawdopodobnie będzie fajna seria we współpracy z pewną bardzo doświadczoną osobą :).
Witaj Piotrze,
kiedy planujesz wrzucić kolejny odcinek ?
Oraz jakieś plany odnośnie wrzucenia refresh tokena i .net core 2.0 ?
Pozdrawiam
Arek
Cześć,
Powinien być na dniach :).
Pozdrawiam