Time: Approximately 15 minutes
Difficulty: Medium
By the end of this exercise you will:
- Learn how to create a CNAB from scratch
- Learn how to use Docker App as a CNAB client
Let's put our hands on what we just saw in the Exercise 6 and create our first CNAB!
-
Create a new directory called
simple
-
Create the following hierarchy (just touching empty files for now):
$ tree simple simple ├── bundle.json └── cnab ├── app │ └── run └── build └── Dockerfile 3 directories, 3 files
We will create a simple bundle.json
, declaring one invocation image and one parameter.
- Edit
simple/bundle.json
- Add an invocation image with the following name
username/simple:1.0.0-invoc
(:warning: use your own docker hub account). - Add an
integer
parameter calledport
and available as an environment variable ($PORT_PARAMETER
). Add its parameter definition.
Solution
{
"name": "simple",
"version": "1.0.0",
"description": "a very simple CNAB Bundle",
"maintainers": [
{
"name": "DAP Workshop",
"email": "dapworkshop@docker.com"
}
],
"invocationImages": [
{
"imageType": "docker",
"image": "username/simple:1.0.0-invoc"
}
],
"definitions":{
"port":{
"maximum":65535,
"minimum":1024,
"type":"integer"
}
},
"parameters":{
"port":{
"definition":"port",
"destination":{
"env":"PORT_PARAMETER"
}
}
},
"schemaVersion":"v1.0.0"
}
We will create a simple bash script which can react to CNAB actions.
- Edit
simple/cnab/app/run
- Read the environment variable
CNAB_ACTION
and print a specific action result on the standard output. It must also fail if the action is unknown. According to ourbundle.json
, it must understandinstall
/upgrade
/uninstall
actions. - For each action, print the installation name.
- The
install
action must print the bundle name and the bundle version. - The
install
andupgrade
actions must print theport
parameter (in$PORT_PARAMETER
).
Solution
#!/bin/sh
action=$CNAB_ACTION
name=$CNAB_INSTALLATION_NAME
case $action in
install)
echo "Install action"
echo "Bundle $CNAB_BUNDLE_NAME version $CNAB_BUNDLE_VERSION"
echo "Port $PORT_PARAMETER"
;;
uninstall)
echo "Uninstall action"
;;
upgrade)
echo "Upgrade action"
echo "Upgraded port $PORT_PARAMETER"
;;
*)
echo "Failure: unknown action $action"
exit 1
;;
esac
echo "Action $action complete for $name"
Solution
FROM alpine:3.9.3
COPY cnab/app/run /cnab/app/run
RUN chmod +x /cnab/app/run
CMD /cnab/app/run
$ cd simple
$ docker build -t username/simple:1.0.0-invoc -f cnab/build/Dockerfile .
[+] Building 0.7s (7/7) FINISHED
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 109B 0.0s
=> [internal] load metadata for docker.io/library/alpine:3.9.3 0.3s
=> CACHED [1/2] FROM docker.io/library/alpine:3.9.3@sha256:28ef97b8686a0b5399129e9b763d5b7e5ff03576aa5580d6f4182a49c5fe1913 0.0s
=> [internal] load build context 0.1s
=> => transferring context: 86B 0.0s
=> [2/2] COPY cnab/app/run /cnab/app/run 0.1s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:03addb3d4bab4e50084921db9a14decf1bc7a86fe18d62c7e7676c33665e8e5c 0.0s
=> => naming to docker.io/library/simple:1.0.0-invoc 0.0s
We have now a bundle.json
AND an invocation image simple:1.0.0-invoc
! Congratulations you have made your first CNAB bundle!!! 🎉
It's time to play with it using Docker App!
Now we need push the invocation image on the hub to make it available, before pushing the bundle itself.
$ docker push username/simple:1.0.0-invoc
Then we will use cnab-to-oci
, the standard tool to push and pull CNAB bundles to a registry.
NOTE: Sources can be found here https://github.com/docker/cnab-to-oci
You will find the tool in your home directory: ~/cnab-to-oci
$ ./cnab-to-oci push simple/bundle.json --auto-update-bundle --target username/simple:v0.1
Starting to copy image username/simple:1.0.0-invoc...
Completed image username/simple:1.0.0-invoc copy
Pushed successfully, with digest "sha256:f0bbfb67115b8517f3880a00f7b179208961482a2c7cb4591c6407edc72ee971"
🎉 Our bundle has been pushed on the Docker Hub and is now available for docker app!
Docker App is a standard CNAB runtime. It can execute the following actions on any CNAB bundle:
- install
- upgrade
- uninstall
EXERCISE: Let's play a little with our bundle, try to run, upgrade with another port, then remove the application.
Solution
- Run the application:
$ docker app run username/simple:v0.1 --name simple_app --set port=4242
Unable to find application image "username/simple:v0.1" locally
Pulling from registry...
Install action
Bundle simple version 1.0.0
Port 4242
Action install complete for simple_app
Application "simple_app" installed on context "default"
- upgrade the application using a new port
$ docker app upgrade simple_app --set port=9090
Upgrade action
Upgraded port 8080
Action upgrade complete for simple_app
Application "simple_app" upgraded on context "dev"
- rm the application
$ docker app rm simple_app
Uninstall action
Action uninstall complete for simple_app
Application "simple_app" uninstalled on context "dev"