Search by Tags

Modifying TorizonCore Debian Based Container Images

 

Article updated at 01 Dec 2020
Compare with Revision




Subscribe for this article updates

Select the version of your OS from the tabs below. If you don't know the version you are using, run the command cat /etc/os-release or cat /etc/issue on the board.



Remember that you can always refer to the Torizon Documentation, there you can find a lot of relevant articles that might help you in the application development.

Torizon 5.0.0

Introduction

Toradex provides Docker Debian-based container images. In order to take full advantage of them, this article will show you how to modify them to fit your necessities, here are two ways to modify our container images:

  • Run commands directly in a container (useful only to develop the Dockerfile or for quick prototyping)
  • Write Dockerfile (most commonly used and recommended method)

IDE Extensions

To abstract away the need for writing Dockerfiles, making your life easier, we have created IDE extensions. Consider using them before diving deep into how to manually modify a Dockerfile:

This article complies to the Typographic Conventions for Torizon Documentation.

Prerequisites

To have a better understanding of this article the following prerequisites are proposed:

Build a Container based on TorizonCore's Debian-based Docker Images

Working in the Container

It is common to quickly test changes in a running container before you actually build your own customized container image. This can also be a useful method to debug issues that can occur when building a container image.

Let's start by running the base Debian image.

$ docker run -it torizon/debian:$CT_TAG_DEBIAN /bin/bash

This should place you in a terminal prompt within the Debian container.

From here you can execute commands and install any package provided by the Debian distribution. For example perhaps you'd want the nano text editor.

$$ apt-get update && apt-get nano

As you can see by just running commands in the container directly you can quickly validate and test your customized container.

It should be noted that this method should only be used for early development and that to truly create your own container image a Dockerfile should be used.

Writing a Dockerfile

In this section we will actually build a container image in a way that is reproducible and can be versioned controlled. For these reasons this should generally be the go-to method when modifying another container image.

Begin by creating a file named Dockerfile, this acts as the "source" file for a container image. In this case we are going to add the nano text editor like we did in the above section:

Dockerfile
FROM torizon/debian:$CT_TAG_DEBIAN RUN apt update && apt install nano -y

Note: a standard Dockerfile has no extension, therefore make sure your file is not named Dockerfile.txt, especially since file extensions are hidden by default. Consult this lesson's FAQ for details about naming.

After creating the file, you can log in to your Docker account:

$ docker login

Now that you are logged to your credentials and the file was created, it's time to finally build your image:

$ docker build -t <username>/<my-container-image> .

Here we can see how working with Dockerfiles have a similar workflow to standard software development (change -> build -> push). For more information on Dockerfiles please reference the official Docker documentation here.

Deploying to the Board

Once you've built your container image using a Dockerfile, you then have a couple of options when it comes to deployment:

  • Docker push and pull: you use the convenient docker push and docker pull commands to only update layers that were modified. It has the drawback that you always must communicate to the Docker Hub server, which is not ideal for development.
  • Local registry push and pull: the idea is the same as the previous one, except you keep a local registry and don't need a connection with the Docker Hub. It's faster and you keep things inside of your LAN. It is a nice approach for developmnet.
  • Docker save and load: you use the commands docker save and docker load to pack/unpack the entire image in a tar file. While you can do development on a LAN, it does deploy the entire image every time, instead of layers. On the other hand, you don't need to setup a local registry.

See them in more detail below in the following sub-sections.

Note: username makes reference to your Docker Hub username. my-container-image to the container image name you are building/pulling.

Docker Push and Pull

The first option is to use the traditional docker push/pull method. This requires a dockerhub account or some other container registry to push your container image to. First we push the container image.

$ docker push <username>/<my-container-image>

Now your container image can be accessed on any other device such as your computer on module running TorizonCore.

# docker pull <username>/<my-container-image>

Local Registry Push and Pull

First you must setup a local registry. While it can get fancy, you just need to run a single command on your development PC to get the basics running:

$ docker run -d -p 5000:5000 --restart=always --name registry registry:2

You must make sure that your image tags are pointing to your local registry. You can either build them already with the local registry tag, or create an additional tag for an existing image:

Build with tag pointing to local registry
$ docker build -t localhost:5000/<my-container-image> .

Create an additional tag for an existing image, pointing to local registry. You can get the tag from the latest container image build. 
$ docker tag <my-container-image-tag> localhost:5000/<my-container-image>

Then on your local PC you can use docker push and docker pull commands as described in the previous section of this article, except you must prefix the image names with your local registry (often you want to just push, since you are cross-building for the target):

$ push
docker push localhost:5000/<my-container-image>

$ pull
docker pull localhost:5000/<my-container-image>

On the board, before being able to push and pull, you need to create a rule to allow an insecure registry. Remember that we only go through the basics, but you can setup a secure local Docker registry if you want or need to. On the board, create a file named /etc/docker/daemon.json and add your local registry's PC IP and port to the insecure registries:

/etc/docker/daemon.json
{
  "insecure-registries" : ["IP-of-my-PC:5000"]
}

Then reboot or restart the Docker daemon. Now you can push and pull to your local registry from your board (often you want to just pull, since you are cross-building on the PC, not on the board):

$ push
docker push localhost:5000/<my-container-image>

$ pull
docker pull localhost:5000/<my-container-image>

Keep in mind, if you are having trouble consult the Docker documentation:

Docker Save and Load

The other option for deployment uses docker load/save. First you'll save your docker image as a portable tar archive file.

$ docker save -o my-dockerfile.tar <username>/my-dockerfile

Then you can copy this tar archive to your target device.

$ scp my-dockerfile.tar torizon@X.X.X.X:/home/torizon/

Finally you can then load the tar archive which will then put the container image on your target device.

# docker load -i my-dockerfile.tar

Docker Multi-stage Build

Downloading the final image takes a lot of time and space, so it's very important to keep it tiny. With multi-stage builds, you can build a docker image in stages with multiple FROM instructions in your Dockerfile. Each FROM instruction starts a new build stage and you can copy only the layers which are necessary from the previous stage. This is very useful to avoid including build dependencies in your final image and it also becomes easier to understand.

For more information, please refer to Docker Multistage documentation.

Next Steps

Torizon 4.0.0

Introduction

Toradex provides Docker Debian-based container images. In order to take full advantage of them, this article will show you how to modify them to fit your necessities, here are two ways to modify our container images:

  • Run commands directly in a container (useful only to develop the Dockerfile or for quick prototyping)
  • Write Dockerfile (most commonly used and recommended method)

This article complies to the Typographic Conventions for Torizon Documentation.

Prerequisites

To have a better understanding of this article the following prerequisites are proposed:

Build a Container based on TorizonCore's Debian-based Docker Images

Working in the Container

It is common to quickly test changes in a running container before you actually build your own customized container image. This can also be a useful method to debug issues that can occur when building a container image.

Let's start by running the base Debian image.

$ docker run -it torizon/arm32v7-debian-base /bin/bash

This should place you in a terminal prompt within the Debian container.

From here you can execute commands and install any package provided by the Debian distribution. For example perhaps you'd want the nano text editor.

$$ apt-get update && apt-get nano

As you can see by just running commands in the container directly you can quickly validate and test your customized container.

It should be noted that this method should only be used for early development and that to truly create your own container image a Dockerfile should be used.

Writing a Dockerfile

In this section we will actually build a container image in a way that is reproducible and can be versioned controlled. For these reasons this should generally be the go-to method when modifying another container image.

Begin by creating a file named Dockerfile, this acts as the "source" file for a container image. In this case we are going to add the nano text editor like we did in the above section:

Dockerfile
FROM torizon/arm32v7-debian-base RUN apt update && apt install nano -y
Dockerfile
FROM torizon/arm64v8-debian-base RUN apt update && apt install nano -y

Note: a standard Dockerfile has no extension, therefore make sure your file is not named Dockerfile.txt, especially since file extensions are hidden by default. Consult this lesson's FAQ for details about naming.

After creating the file, you can log in to your Docker account:

$ docker login

Now that you are logged to your credentials and the file was created, it's time to finally build your image:

$ docker build -t <username>/my-dockerfile .

Here we can see how working with Dockerfiles have a similar workflow to standard software development (change -> build -> push). For more information on Dockerfiles please reference the official Docker documentation here.

Deploying to the Board

Once you've built your container image using a Dockerfile, you then have a couple of options when it comes to deployment.

Docker Push and Pull

The first option is to use the traditional docker push/pull method. This requires a dockerhub account or some other container registry to push your container image to. First we push the container image.

$ docker push <username>/my-dockerfile

Now your container image can be accessed on any other device such as your computer on module running TorizonCore.

# docker pull <username>/my-dockerfile

Docker Save and Load

The other option for deployment uses docker load/save. First you'll save your docker image as a portable tar archive file.

$ docker save -o my-dockerfile.tar <username>/my-dockerfile

Then you can copy this tar archive to your target device.

$ scp my-dockerfile.tar torizon@X.X.X.X:/home/torizon/

Finally you can then load the tar archive which will then put the container image on your target device.

# docker load -i my-dockerfile.tar

Docker Multi-stage Build

Downloading the final image takes a lot of time and space, so it's very important to keep it tiny. With multi-stage builds, you can build a docker image in stages with multiple FROM instructions in your Dockerfile. Each FROM instruction starts a new build stage and you can copy only the layers which are necessary from the previous stage. This is very useful to avoid including build dependencies in your final image and it also becomes easier to understand.

For more information, please refer to Docker Multistage documentation.

Next Steps