Docker Demos — Saving, importing, and running a container

Introduction

It’s been a while, but thank you for checking in again! In one of our previous tutorials, we built a basic Docker container using nothing more than an Alpine Linux image and some container notes. As we’ve seen in other tutorials, we can extend this to run a myriad of other programs within the container on startup. But what good is a container if it can’t be shared? To do so, we need to learn a few new things: how to save a container, how to share a container, and how to load a container. Let’s get started, shall we?

The Setup

As stated in the introduction, we’re going to keep this tutorial simple. The main flow will be something like this:

  • Build a single Docker container on a light-weight Alpine Linux image
  • Enable the Alpine image with Python (and pip)
  • Create a simply Python file for the container to run on startup
  • Build the container and export as an image
  • Move the image to a different folder to emulate container sharing
  • Unpack and run the “shared” container

Docker file

Since we’ve seen many of these steps before, I’ll defer the explanations to previous Docker Demo tutorials. For brevity, the purpose of each step is added as a comment above each command in the dockerfile.

# Define base image of the container
FROM alpine:3.14 AS build

# Add notes to the container
LABEL version = "1.0"
LABEL description = "A more advanced Docker file!"

# Define Python environment / install python & pip
ENV PYTHONUNBUFFERED=1
RUN apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python
RUN python3 -m ensurepip
RUN pip3 install --no-cache --upgrade pip setuptools

# Copy our Python script from local to the container
COPY ./hello.py .

# Auto-run the Python script
CMD ["python","hello.py"]

Python file: hello.py

Similar to how we kept things simple with our dockerfile, let’s go ahead and do the same thing with a very basic Python file. Here, the Python file only prints out a single line of text, “Greetings, friends!”. Keep in mind, the Python script file is expected to be in the same location as our Dockerfile!

print("Greetings, friends!")

Building the Docker container

So far, we’re still in familiar territory. Let’s go ahead and build our Docker container with commands we’ve already learned:

docker build --no-cache -t dockerfile:v0 .
[+] Building 14.6s (10/10) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                                                                         0.0s 
 => [internal] load .dockerignore                                                                                                                                                                            0.0s 
 => => transferring context: 2B                                                                                                                                                                              0.0s 
 => [internal] load metadata for docker.io/library/alpine:3.14                                                                                                                                               0.4s 
 => CACHED [1/5] FROM docker.io/library/alpine:3.14@sha256:4c869a63e1b7c0722fed1e402a6466610327c3b83bdddb94bd94fb71da7f638a                                                                                  0.0s 
 => [internal] load build context                                                                                                                                                                            0.1s 
 => => transferring context: 29B                                                                                                                                                                             0.0s 
 => [2/5] RUN apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python                                                                                                                          2.7s 
 => [3/5] RUN python3 -m ensurepip                                                                                                                                                                           5.0s 
 => [4/5] RUN pip3 install --no-cache --upgrade pip setuptools                                                                                                                                               5.7s 
 => [5/5] COPY ./hello.py .                                                                                                                                                                                  0.1s 
 => exporting to image                                                                                                                                                                                       0.5s 
 => => exporting layers                                                                                                                                                                                      0.4s 
 => => writing image sha256:c6a7cb4e5423410574e3859e344cfb0f8b1a3f485fe49211e2ee969aecad1e1f                                                                                                                 0.0s 
 => => naming to docker.io/library/dockerfile:v0      

Now that our container has been built into an image (dockerfile:v0), we can run it in interactive mode (docker run -it dockerfile:v0):

docker run -it dockerfile:v0
Greetings, friends!

The output here is no surprise, but it confirms that everything we’ve done so far works perfectly, and that we’re using the correct image name.

Exporting a Docker container

With the old stuff out of the way, on to our new topic: exporting a Docker container. Similar to what we’ve seen in previous tutorials, Docker has a very nice and simple syntax for achieving the image export: docker save. In fact, the documentation states that not only can we cherry pick particular tags we want to export, but we can also choose the name of the export file, as well! The syntax to do so follows this format:

docker save -o <output_file_name>.tar <image_tag>

Since this exports as to a tar archive format, we can even peek inside the image using Windows Explorer; doing so, however, is not terribly revealing. We are presented with a list of alpha-numerically named folders, a repositories file and a manifest.json file…neither of which are immediately readable.

With this in mind, let’s go ahead and export our new container, tagged dockerfile:v0 as a randomly named tar archive file, littleduck.tar. Although no output is shown, a new file (littleduck.tar) is added to the same file directory as our dockerfile.

PS C:\Desktop\docker demo> docker save -o littleduck.tar dockerfile:v0
PS C:\Desktop\docker demo> 

Sharing the Docker image

If we open a Windows Explorer to the folder where our dockerfile resides, we see that the size of the exported Docker image is ~48 MB. The size is mainly due to not only the Docker dependencies installed within our container, but also the size of the Python installation, and, to a lesser degree, the size of the Alpine operating system we used as the base image for our container.

The smallish file size means it can be easily migrated to a server, e-mailed to a colleague, or placed on DockerHub. However, if DockerHub if your preferred method of sharing your Docker images, you’ll be much better off using Git-like commands… but we’ll cover this in another tutorial. For now, let’s just say a friend has e-mailed us the file, and we’ve saved it in another folder. Since my files for this demo are located in C:\Desktop\docker demos\, I’ll copy the new container to a separate folder, C:\Downloads\.

Within the Downloads folder, I can press Shift and right click, selecting “Open Powershell Window here”. Within Powershell, I can run two commands — the first verifies the existence of our new Docker image archive, and the second confirms that Docker is callable via the Docker environment variable.

PS C:\Downloads> ls

    Directory: C:\Downloads

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        11/23/2022   9:10 AM       50614894 littleduck.tar


PS C:\Downloads> docker
Usage:  docker [OPTIONS] COMMAND
A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default
                           "C:\\Users\\aaron\\.docker")

Importing the Docker image

With the new Docker image verified within our “new” folder, we can use another straight-forward Docker command to load the file: docker load. Since we are calling Powershell within the Downloads folder, we can simply use the following syntax:

docker load -i <file_name>

Here, the -i flag stands for --input, and our file name is simply the direct path of our new .tar file. Within the Downloads folder, then, we can execute the load command, followed by our normal docker run -it <image_name> command:

C:\Downloads>docker load -i .\littleduck.tar
Loaded image: dockerfile:v0

C:\Downloads>docker run -it dockerfile:v0
Greetings, friends!

Aha, success! The first output generated by the Windows terminal / Powershell shows the .tar file was successfully unpacked, and our image, dockerfile:v0 was loaded into the Docker environment. From here, we further validate the image’s operation via the output string, “Greetings, friends!”

Conclusion

In this tutorial, we’ve really come full-circle. Starting from scratch, we’ve now built a Docker container with Python functionality, and saved the compiled image into an external file. We’ve probed the image file in Windows Explorer, and we’ve moved the file to an arbitrary location on our computer — a simulation of sharing the file with others. From there, we called basic Docker commands to successfully load and import the image. Lastly, we ran the image and demonstrated its proper output.

So where do we go from here? Again, it’s your choice! Feel free to drop a suggestion in the comments below and let me know what topics you’d like to see covered. Until then, thanks again for learning with me — we’re all in this together! If you’re enjoying the content, please feel free to Like, comment, and subscribe — see you next time!

Get new content delivered directly to your inbox.

Advertisement

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: