Using Docker inside Porter Bundles
Sometimes you need a hammer, and that hammer happens to be a whale 🐳. We all use containers as part of our pipeline: building images, running a one-off command in a utility container, spinning up a test environment to verify your application, or even more creative tasks that you have already containerized. Well now you can reuse all that hard work and logic from within your bundles!
Let’s walk through using my favorite container, docker/whalesay, in a bundle.
_____________________
< Challenge Accepted! >
---------------------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
Author the bundle
Writing a bundle that uses Docker has a few steps:
Here’s the full working example whalesay bundle for you to follow along with.
Require Docker
The user running the bundle, and Porter, needs to know that this bundle requires the local Docker daemon connected to the bundle. You need to a new section to porter.yaml for required extensions, and defined a new prototype extension that says that the bundle requires access to a Docker daemon:
required:
- docker
Optionally you can include that you also want the bundle to be run with
--privileged
which is intended for docker-in-docker scenarios:
required:
- docker:
privileged: true
Install Docker
You can include the Docker CLI in your bundle by using the docker mixin.
mixins:
- docker
You can then use the respective CLIs through the mixin:
install:
- docker:
description: "Run my container"
run:
image: hello-world
rm: true
This blog post focuses on just the docker mixin, but here is a full working example for how to use Docker Compose in a bundle.
Use Docker
In my porter.yaml, I can use the docker mixin to execute docker commands in my bundle:
porter.yaml
name: examples/whalesay
version: 0.2.0
description: "An example bundle that uses docker through the magic of whalespeak"
registry: ghcr.io/getporter
required:
- docker
parameters:
- name: msg
description: a message for the whales to speak
type: string
default: "whale hello there!"
applyTo:
- say
mixins:
- docker
install:
- docker:
run:
image: "docker/whalesay:latest"
rm: true
arguments:
- cowsay
- Hello World
upgrade:
- docker:
run:
image: "docker/whalesay:latest"
rm: true
arguments:
- cowsay
- World 2.0
say:
- docker:
run:
image: "docker/whalesay:latest"
rm: true
arguments:
- cowsay
- - ${ bundle.parameters.msg }
uninstall:
- docker:
run:
image: "docker/whalesay:latest"
rm: true
arguments:
- cowsay
- Goodbye World
After I test the bundle and verify that it’s ready for release, I use porter publish
to push the new image ghcr.io/getporter/examples/whalesay:v0.2.0
to the registry.
Run that bundle
Now that the bundle is ready to use, the user running the bundle needs to
give the bundle elevated permission with the Allow Docker Host
Access setting. This
is because giving a container access to the host’s Docker socket, or running a
container with --privileged
, has security implications for the underlying host,
and should only be given to trusted containers, or in this case trusted bundles.
Let the whales speak!
$ porter install --reference ghcr.io/getporter/examples/whalesay:v0.2.0 --allow-docker-host-access
installing whalesay...
executing install action from whalesay (bundle instance: whalesay)
Install Hello World
_____________
< Hello World >
-------------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
execution completed successfully!
I can set the flag --allow-docker-host-access
with the PORTER_ALLOW_DOCKER_HOST_ACCESS
environment variable so that I don’t have to specify it for every command.
export PORTER_ALLOW_DOCKER_HOST_ACCESS=true
Now let’s see what else you can do with whalesay:
$ porter invoke whalesay --action=say --param 'msg=try it yourself!'
invoking custom action say on whalesay...
executing say action from whalesay (bundle instance: whalesay)
Say Something
__________________
< try it yourself! >
------------------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
execution completed successfully!
This is hopefully just the first step towards first class support for Docker and Docker Compose within Porter bundles, especially now that Docker Compose has an open specification. If you are interested in collaborating with us to take this further, please reach out on the porter or docker mixin repositories!