# Using Docker
This document will explain how to utilize Docker in order to containerize and deploy a fully developed module so that it can be used on an Edge device. Please note that these are only guidelines, and the Docker website should be consulted for best practices, full documentation, and usage guidelines.
# Prerequisites
This tutorial assumes that the associated module is written as a .NET Core library. Sample code can be found at the codebits repository.
Before starting this tutorial, you should have the binary files for your project compiled on your local machine.
# Requirements
- The local machine is running Windows 10 using Docker Desktop for Windows, or an earlier version of Windows using Docker Toolbox.
- An IDE capable of handling C# is being used for development, such as Visual Studio Code with the C# Extension, or Visual Studio.
- The .NET Core SDK is installed. That the user is familiar with the .NET framework is recommended, but not required.
# Building the Docker Image
# Docker Files
In order to build an image through Docker, a Dockerfile must be provided. A Dockerfile contains all the information and commands, in order, that are required to build the resulting image. Each command used by Docker during the build process results in a layered, or intermediate, image. This allows Docker to update only the image where necessary as changes occur to the Dockerfile.
Here is an example of a Dockerfile used to build the send-telemetry module:
FROM mcr.microsoft.com/dotnet/core/runtime:2.2
ARG EXE_DIR=.
COPY ${EXE_DIR}/bin/Release/netcoreapp2.2/publish/* /cst-csharp-sendtelemetry/
ENTRYPOINT ["dotnet", "/cst-csharp-sendtelemetry/ABB.Ability.IotEdge.CST.Modules.CSharp.SendTelemetry.dll"]
The FROM
declaration in this file defines the base image that the project is
going to be built upon. This will be the first intermediate image generated by
Docker. It is considered best
practice
to use a base image where possible, but you may start from an empty image by
specifying FROM scratch
.
The ARG
declaration is similar to declaring variables in a set of code. ARG
declarations can be used later in the script. It is important to note that ARG
values are not accessible in the final container and should not be used for
sensitive data as it is easy to view these values.
COPY
tells the Docker build process which directory to include during the
build. Since .NET Core applications write to the /bin directory, this is used
for the send-telemetry module.
Finally, the ENTRYPOINT
parameter will be used to instruct the container what
to do on start up. Since this is a .NET application, the dotnet
command is
used to start the application.
There are many other Docker commands that can be used within the Dockerfile that are outside the scope of this tutorial. For a complete list, please refer to the Dockerfile reference guide.
TIP
Docker images can be built using versioning by following a name:version
pattern when executing docker build
. This can be useful in ensuring you are always using the latest version of your custom image.
# Image Layering
When composing a docker image, special care should be taken to the order of the instructions provided in the Dockerfile. As Docker creates intermediate images throughout the build process, the most likely to change instructions should come as close to the end of the Dockerfile as possible. This will prevent unnecessary additional intermediate images from being created in future builds.
# .dockerignore
A file titled .dockerignore
can be added to the same directory as the
Dockerfile in order to prevent certain files from being used during the build
process. This functions similar to a .gitignore
. More information is available
here.
This is very useful for ensuring that the resulting image is as lean as
possible.
# Using a Published Image
Utilizing a published image requires an additional step. The type definitions for the Edge and the module must be uploaded via the Type Definition Registry API.
Once all of these steps are complete, you can follow the instructions available in the Edge Setup documents, replacing the referenced EDGE_TYPE with your type definitions, to achieve a running Edge using your new docker container.