Containerize an application
In the following guide you will try and deploy a simple Node.js webapp, based on Docker’s get-started guide. This guide does not go into details of the webapp, so no prior knowledge of Node.js or JavaScript is required.
Pre-requisites
- A conceptual understanding of containers and images.
- Kleened and Klee installed and configured on the host so they can communicate with each other.
git
Get the app
Before you can run the application, you need to get the application source code onto your machine.
-
Clone the getting-started repository using the following command:
$ git clone https://github.com/docker/getting-started.git
-
View the contents of the cloned repository. Inside the
app
root-directory of the repository you should see apackage.json
, two subdirectories (src
andspec
), and perhaps a few other files.
Prepare the Kleened host
When you have a fresh installation, a few preparations is needed before you can start building images and creating containers.
You need to create a base image and a network to use for the images and containers that are created in this guide.
-
Create a base image. The simplest way to do this is to let Kleened find and download an approriate relase of the FreeBSD userland:
$ klee image create fetch-auto
-
Optional: In order for you to isolate your containers from the host networking create a dedicated network to use for our containers:
$ klee network create --subnet 10.13.37.0/24 testnet
It is recommended to connect containers to a network, instead of using the default
host
network driver for connectivty. Using networks provides a higher degree of isolation from the host’s networking configuration. If you decide to use thehost
network driver instead, remember to omit the-n testnet
option when creating containers in this guide.
Build the app’s container image
In order to build the container image, you’ll need to use a Dockerfile
.
A Dockerfile contains the instructions that Kleened uses to create the image.
-
In the
app
directory mentioned previously, create a file namedDockerfile
.You can use the following commands below to create a Dockerfile, replacing
/path/to/
with the path to yourgetting-started
repository.$ cd /path/to/app $ touch Dockerfile
-
Add the following contents to the Dockerfile:
FROM FreeBSD-13.2-RELEASE:latest RUN pkg install -y node20 npm-node20 yarn-node20 WORKDIR /app COPY . . RUN yarn install --production # Listens on port 3000 CMD cd /app && node src/index.js
Note
Click on an instruction in the Dockerfile example to learn more about the instruction.
-
Build the container image, and assuming you are still in the
app
directory, run$ klee build -t webapp .
to build the container image.
Kleene uses the Dockerfile to build a new container image.
The Dockerfile
starts with FROM FreeBSD-13.2-RELEASE:latest
that refers to the base-image we created previously,
so it will be used as the foundation for our new webapp
image.
The remaining instructions from the Dockerfile installs the application dependencies, copies application data into the image, and uses yarn
to install the application’s JavaScript dependencies.
The CMD
directive specifies the default command to run when starting a container from this image, which in this case is set to run the application.
Finally, the -t
flag tags your image. Think of this simply as a human-readable name for the final image. Since you named the image webapp
,
you can refer to that image when you run a container. Since we have not specified a tag
, Kleene tags the image with latest
.
The .
at the end of the klee build
command tells Kleene that it should look for the Dockerfile
in the current directory.
Note
The directory
.
is converted to its absolute path by Klee and then sent to Kleened. Kleened will then interpret this as a path on the host machine where it is running. If Klee and Kleened are runnning on the same host this is fine, but if Klee is running on a remote machine this will probably not work. In the latter case, remember to use absolute paths on the host machine where Kleened is running.
Start an app container
Now that you have an image, you can run the application in a container.
To do so, you will use the klee run
command.
-
Start your container and specify the name of the image you just created:
$ klee run -n testnet -d webapp
Using
-n testnet
connects the new container to our recently createdtestnet
network, providing connectivity for thewebapp
container. The new container runs in “detached” mode (in the background) when the-d
flag is used. - Verify that the container is running as expected using
klee lsc
. This command shows the id and auto-generated name of your new container. It is also possible to verify that the container is running using the FreeBSD native tooljls
:$ jls JID IP Address Hostname Path 6 10.13.37.1 /zroot/kleene/container/d23e37375ffd
This also shows the ip address of the container that is needed for accessing the web application. Note that the IP is shown because the container uses the
ipnet
network driver. -
After a few seconds, open your web browser to http://10.13.37.1:3000. If you are not running the container locally you might need to access the app at another location or use a port forward etc. For example, using portforward with
ssh
such asssh -L 3000:10.13.37.1:3000 ...
you should be able to access the web application on http://localhost:3000 instead. - Go ahead and add an item or two and see that it works as you expect. You can mark items as complete and remove items. Your frontend is successfully storing items in the backend.
At this point, you should have a running todo list manager with a few items, all built by you.
Note that our images and containers are just zfs datasets one the host. Use zfs list
to get an overview of how Kleene
stores its objects.
Next steps
Next, you’re going to make a modification to your app and learn how to update your running application with a new image. Along the way, you’ll learn a few other useful commands.