Flavio Poletti

Irreducible Perler.

Email Comics Twitter LinkedIn MetaCPAN Github Stackoverflow Pinterest

Dibs - Meet The Packs

This is the first post about dibs (first here and second here) and it should be clear by now that the main goal of Dibs (at least “over” using a plain Dockerfile) is reuse. This time we take an introductory look at packs, which per-se allow easily reusing stuff in a slightly less copy & paste way; we will see in a future installment how this can be further leveraged for a more modern way of sharing and reusing things.

Curious about the whole Dibs Saga? See a list of all posts on dibs.

First Look At Packs

We already looked at packs, e.g. in our first article we can find this:

actions:
# ...
build:
# ...
- name: build
pack:
run: |
#!/bin/sh
set -e
exec >&2
apk --no-cache add build-base wget perl perl-dev
wget -O /bin/cpanm --no-check-certificate https://cpanmin.us/
chmod +x /bin/cpanm
cd /app
cp -R /tmp/src/* .
cpanm -l local --notest --installdeps .
END
cp -a /app /tmp/cache

It turns out that a sketch action (any sketch action!) needs a pack to know what should be factually done inside the container. Hence, you will always see something like this:

actions:
# ...
some-sketch-action:
pack: # ... whatever defines the pack
# ...

The example above with the run section was just possibly the simpler kind of pack, that is one whose implementation is fit directly inside Dibs’s configuration file. There can be more, of course.

A Library Of Packs

The next “simple” place where you can put a pack is an executable program (be it a shell script of anything that you can run inside the target container). Where should you place this file eventually? There are a few options, but for the moment we will play it easy and opt for the pack sub-directory of the project directory.

Evolving our previous example, we can fit the shell script in a file inside pack, e.g. pack/kickoff.sh:

#!/bin/sh
set -e
exec >&2
apk --no-cache add build-base wget perl perl-dev
wget -O /bin/cpanm --no-check-certificate https://cpanmin.us/
chmod +x /bin/cpanm
cd /app
cp -R /tmp/src/* .
cpanm -l local --notest --installdeps .
END
cp -a /app /tmp/cache

Then, we change the configuration file to use it:

actions:
# ...
build:
# ...
- name: build
pack:
project: kickoff.sh

The same script might be reused multiple times across the same configuration file. We already learned to use YAML variables to avoid repetition, but there’s a semantic way to do this as well, i.e. put definition of packs inside a packs section at the top level, like this:

packs:
kickoff: # we choose the "explicit" way, it's the same as above
type: project
path: kickoff.sh
actions:
# ...
build:
# ...
- name: build
pack: kickoff    # same name inside "packs" above

In this way, you can save your scripts as standalone files and manage (e.g. edit, track, etc.) individually with little effort to eventually call them during container build-up.

args: Making Packs More Reusable

A program that only does one thing in the same way might become dull very quickly and leave you the temptation to copy and paste to get something slightly different. Dibs actively wants you to stop this waste!

When you call a program in a pack, you can also pass arguments that will appear as command-line arguments to the program itself. As an example, save this as pack/alpine-packs.sh:

#!/bin/sh
set -e
exec >&2
apk --no-cache add "$@" Now you can have this kind of definition: packs: alpine_packs: type: project path: alpine-packs.sh actions: # ... build: # ... - name: Install OS packs pack: alpine_packs args: - build-base - wget - perl - perl-dev # ... bundle: # ... - name: Install OS packs pack: alpine_packs args: - perl … And, Of Course, Environment Variables Command-line arguments via options args are not the only way to tell your programs about behaving differently. Another way would be defining environment variables instead, via the env key. The following example transforms the one in the previous section to use an environment variable with the list of space-separated packages to install. Save this as pack/alpine-packs-env.sh: #!/bin/sh set -e exec >&2 # CAUTION: no quotes around expansion of ALPINE_PACKAGES apk --no-cache add$ALPINE_PACKAGES

Now you can have this kind of definition:

packs:
alpine_packs_via_environment:
type: project
path: alpine-packs-env.sh
actions:
# ...
build:
# ...
- name: Install OS packs
pack: alpine_packs_via_environment
env:
- ALPINE_PACKAGES: 'build-base wget perl perl-dev'
# ...
bundle:
# ...
- name: Install OS packs
pack: alpine_packs_via_environment
env:
- ALPINE_PACKAGES: 'perl'

Enough For Now

Today we learned:

• you can place your programs (e.g. scripts) in standalone files inside the project tree and avoid bloating your configuration file
• it is very, very easy to use these outside-placed programs from sketches
• you have at least a couple ways to make these programs generic, i.e. either make them accept command-line arguments, or work based on environment variables.

There’s more than this… but it’s enough for now. As usual, let me know what you think in the comments.