Hello world¶
No more words, it’s time for code!
import docked as d
stage = d.Stage(
base=d.BaseImage('python', tag='3.11-alpine'),
build=[
d.RUN(
d.cmd.pip_install('cowsay'),
),
],
run=[
d.CMD(['cowsay', 'hello world!'])
],
)
image = d.Image(stage)
if __name__ == '__main__':
image.lint()
print(image)
What’s happening:
d.Image
is equivalent of a single Dockerfile file. It wraps one or more stages. YOu can have many stage in per image in multi-stage builds.d.Stage
is a single “stage”. You can have multiple sbase=d.BaseImage(...)
is the image on which the stage is based. It can be anything available on Docker Hub.build=[...]
is a list of steps to perform when building the image. Most of the steps correspond to a Docker instruction with the same name.d.RUN(...)
is the same as RUN in Docker. It tells to run a list of the given shell-commands when building the image.d.cmd.pip_install
is a convenience function that will produce a command forpip
to install the given packages. It’s better than just passingpip install cowsay
because it will produce a command that follows the best practice of installing Python packages in Docker images. Docked provides a few most useful convenience functions but not many, we don’t want it to be too verbose.run=[...]
is a list of Docker instruction describing not how the image should be build but how it will behave when it is run. A good example is VOLUME which cannot mount volumes when building an image, and so it can be passed inrun=[...]
but not inbuild=[...]
image.lint()
runs built-in linter that will make sure we follow the best practice of building Docker images.print(image)
generates a Dockerfile and prints it into stdout.
Now, pipe it into docker and run the image:
python3 examples/cowsay.py | docker buildx build --tag=hello:latest -
docker run hello:latest
And you should see Mr. Cow:
____________
| hello world! |
============
\
\
^__^
(oo)\_______
(__)\ )\/\
||----w |
|| ||