Pipelines ships with some hard-encoded packages for a smaller number of different docker client versions including the exact same one at the time of writing that is used by Atlassian Bitbucket Cloud Pipelines Plugin.
These packages are meta-data information on how to obtain a static binary of the Docker client and allow to use a static Docker client binary in a reproducible manner.
Static Docker client binaries are useful for pipelines
as they can be
mounted into nearly any Linux container without further installation
requirements (next to provide connectivity to the Docker daemon).
This document is about how-to obtain the static docker client binary and all the meta-data to make use of it and also on how to create such packages next to existing packages or for improving pipelines with new package definitions.
Be it a local .yml
package file, a package that ships with the
pipelines utility or a custom build static docker client binary.
While doing so, this document also explains many details about the file-
format of .yml
docker client binary packages and the --docker-client
option and arguments as well as the --docker-client-pkgs
option.
These options are generally useful to use a different than the default docker client.
- List all Available Docker Static Binary Packages
- Create Docker Client Static Binary Packages for Pipelines
- Last but not Least: Use a Custom Build Static Docker Client Binary
To display a list of all available docker client versions use the
--docker-client-pkgs
option:
$ bin/pipelines --docker-client-pkgs
docker-17.12.0-ce-linux-static-x86_64
docker-18.09.1-linux-static-x86_64
docker-19.03.1-linux-static-x86_64
docker-42.42.1-binsh-test-stub # only for development version
It shows the list of the built-in packages which can be used right away
as an option to the --docker-client
argument.
This list does not highlight the default one, so here a short description about each of these:
docker-17.12.0-ce-linux-static-x86_64
: this version was in use when using thedocker-client-install.sh
script inside a pipeline.docker-18.09.1-linux-static-x86_64
: this version was found in use by the Atlassian Bitbucket Cloud Pipelines Plugin:$ docker --version Docker version 18.09.1, build 4c52b90
docker-19.03.1-linux-static-x86_64
: the version used mainly to develop pipelines, in specific the Docker Service feature, which was sort of current while doing the development work. It includes fixes in environment variable handling (18.07.0 / docker/cli#1019) which prevented pipelines to properly import environment variables from the users' environment by environment variable files. This became prominent back in April 2018.docker-42.42.1-binsh-test-stub
: a fake package used for testing that is not a Docker client at all. When the pipelines project is cloned, this is the only package that works offline out of the box and is only available aftercomposer install
has been run.
It might not be always in your case that pipelines ships with the package of your wish.
Docker binaries are available for different platforms from the
download.docker.com
website:
Browse for the version that you need to work in a pipeline container, it might be necessary to change the architecture, fiddle with the path component of the URL above.
In writing this how-to the docker-17.12.0-ce.tgz for Linux x86_64 has been created exemplary (it is now part of pipelines):
To download a utility like wget
or similar can be used:
$ wget https://download.docker.com/linux/static/stable/x86_64/docker-17.12.0-ce.tgz
--2019-12-15 17:10:57-- https://download.docker.com/linux/static/stable/x86_64/docker-17.12.0-ce.tgz
Resolving download.docker.com (download.docker.com)... 2600:9000:21c7:ac00:3:db06:4200:93a1, 2600:9000:21c7:a200:3:db06:4200:93a1, 2600:9000:21c7:5c00:3:db06:4200:93a1, ...
Connecting to download.docker.com (download.docker.com)|2600:9000:21c7:ac00:3:db06:4200:93a1|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 34272897 (33M) [application/x-tar]
Saving to: ‘docker-17.12.0-ce.tgz’
docker-17.12.0-ce.tgz 100%[=. .. =>] 32,68M ?,79MB/s in ?,8s
2019-12-15 17:11:02 (6,76 MB/s) - ‘docker-17.12.0-ce.tgz’ saved [34272897/34272897]
As of time of writing, a package in pipelines for the docker client binary contains a bit more meta-information than the download location:
- The name of the package - to identify it, in this how-to we take
docker-17.12.0-ce-linux-static-x86_64
, the name should be portable - The URI - in this how-to it is the https URL of the download package
- The SHA-256 checksum of the download package - to verify if the download was successful (complete)
- The path of the docker binary inside the download package - this path is needed for extraction
- The SHA-256 checksum of the docker binary - to verify extraction from the package was successful (complete)
To create the SHA-256 checksum of the download package:
$ shasum -a256 docker-17.12.0-ce.tgz
692e1c72937f6214b1038def84463018d8e320c8eaf8530546c84c2f8f9c767d docker-17.12.0-ce.tgz
Next look into the download package for the path of the docker client:
$ tar -tvf docker-17.12.0-ce.tgz
drwxr-xr-x 0/1000 0 2017-12-27 21:13 docker/
-rwxr-xr-x 0/1000 4320064 2017-12-27 21:13 docker/docker-containerd-shim
-rwxr-xr-x 0/1000 15433832 2017-12-27 21:13 docker/docker-containerd
-rwxr-xr-x 0/1000 7550928 2017-12-27 21:13 docker/docker-runc
-rwxr-xr-x 0/1000 19938610 2017-12-27 21:13 docker/docker
-rwxr-xr-x 0/1000 760040 2017-12-27 21:13 docker/docker-init
-rwxr-xr-x 0/1000 12773768 2017-12-27 21:13 docker/docker-containerd-ctr
-rwxr-xr-x 0/1000 2517244 2017-12-27 21:13 docker/docker-proxy
-rwxr-xr-x 0/1000 46366152 2017-12-27 21:13 docker/dockerd
It normally is docker/docker
and so it is in this how-to. Locate the
path and create a SHA-256 checksum of it:
$ tar -xf docker-17.12.0-ce.tgz -O docker/docker | shasum -a256
c77a64bf37b4e89cc4d6f35433baa44fb33e6f89e2f2c3406256e55f7a05504b -
Now all required meta-data has been obtained to create a package.
The only thing left to fully produce a package file is to encode the collected information as YAML:
$ <<'YAML' cat > docker-17.12.0-ce-linux-static-x86_64.yml
---
# this file is part of pipelines
#
# binary docker client package format
#
name: docker-17.12.0-ce-linux-static-x86_64
uri: https://download.docker.com/linux/static/stable/x86_64/docker-17.12.0-ce.tgz
sha256: 692e1c72937f6214b1038def84463018d8e320c8eaf8530546c84c2f8f9c767d
binary: docker/docker
binary_sha256: c77a64bf37b4e89cc4d6f35433baa44fb33e6f89e2f2c3406256e55f7a05504b
YAML
When done you find a .yml
file with the name in the current directory.
Note: You can find another description of each part of the package format in the commented package after
composer install
: lib/package/docker-42.42.1-binsh-test-stub.yml
This package .yml
file can already be used for a first test to see if
it works. Just run pipelines
with the --docker-client
option having
the path to the .yml
file as argument:
$ bin/pipelines --pipeline custom/docker \
--docker-client docker-17.12.0-ce-linux-static-x86_64.yml
...
+++ docker client install...: Docker version 17.12.0-ce, build c97c6d6
�+ docker version --format {{.Client.Version}}
17.12.0-ce
...
This runs pipelines with a pipeline that has the docker service and
therefore injects the docker client binary from the package .yml
file
provided by --docker-client
argument. In this case the projects'
custom pipeline named "docker-in-docker" (id: custom/docker
).
The benefit of having a .yml
package file is that all the meta-
information is already documented, including on how to obtain the file.
This includes benefiting for a user-wide store of checksum/hash'ed files.
The tar package files are cached in the XDG_CACHE_HOME
directory,
which by default is:
~/.cache/pipelines/package-docker
As long as the user decides to keep the cache, this spares downloading of the tar package again and again.
The docker client binaries are not cached but kept and stored so that
they are available in user-land until the user decides to remove the
application in the XDG_DATA_HOME
directory:
~/.local/share/pipelines/static-docker
Instead of having a .yml
package somewhere on the local disk it is
better to add it to the pipelines utility itself.
Copy the file into the source directory for package files (here from within a checked-out copy of the pipelines project):
$ cp -vi docker-17.12.0-ce-linux-static-x86_64.yml lib/package
'docker-17.12.0-ce-linux-static-x86_64.yml' -> ...
... 'lib/package/docker-17.12.0-ce-linux-static-x86_64.yml'
To test if the new package name works, invoke Pipelines with the name
of this package (not the full file-name or path, e.g. not the path to
the file but just the basename of it excluding the .yml
extension)
with a pipeline that is making use of the docker service, here exemplary
again with the projects' custom pipeline named "docker-in-docker"
(custom/docker
):
$ bin/pipelines --pipeline custom/docker \
--docker-client docker-17.12.0-ce-linux-static-x86_64
[...]
+++ docker client install...: Docker version 17.12.0-ce, build c97c6d6
�+ docker version --format {{.Client.Version}}
17.12.0-ce
[...]
Note: If you wish to see a specific package of yours also within the upstream distribution feel free to file a pull-request.
Pipelines as an integration utility allows to use docker client binaries directly. For example a binary created from a docker client development build.
In this variant, no package exists at all and the binary is just given
as the --docker-client
options argument as path to the binary. No
download will take place, so is no caching nor adding to any local
store (this is all not needed, the file already exists locally).
The package is only temporary so to say and the meta-information is non-
existent.
This mode of operation is very useful for testing any kind of binary as a docker client.
To distinguish between a package name and binary potentially of that
same name, the --docker-client
argument needs to have at least a
single slash ("/
") in the path to the binary.
For example, if the docker client binary is just a local file in the
working directory prefix it with ./
so that pipelines can understand
it is not a package of the same name.
For example with the test stub that is available in pipelines development:
$ bin/pipelines --pipeline custom/docker \
--docker-client test/data/package/docker-test-stub
[...]
+++ docker client install...: 42.42.1 ( --version )
�+ docker version --format {{.Client.Version}}
42.42.1 ( version --format {{.Client.Version}} )
[...]
Here a fake .sh
script is used as the docker client binary which outputs
a bogus version number (42.42.1
) and all options and arguments with which
it was invoked which makes it suitable for testing purposes.