Let's talk about

First, what is ? This is a software allowing you to build and share filesystem images. This is really useful to get a stable environment across a full team or even across runs for a build system.

When I use a tool, I always wonder "If I had to do it myself, how would I do it?". I don't thrive into the details inside my head, only the main lines, but this simple question help to know if there is some concepts underlying I don't known yet or if this is only a matter of implementation details.

Even if I'm sure I'm not always right, this rule of thumb allowed my to build a great tree of knowledge in my domain, espacially on topics I've never been teached about.

I never looked a the source code but, if I had to do a simple version of it, I would plan something like that:

  • docker image => find or build a filesystem allowing me to stack several layers of filesystem "diff"
  • docker build => use a chroot environment to build the layers of an image one by one
  • docker run => use a chroot environment to stack the layers of an image and give a prompt to the user or run a command
  • docker push/pull => create a system similar to git to organize and store the image layers based on their hashes

When running inside , uses the host kernel, it doesn't pop out a new one. That's why if your looking at the tasks running on your host, you will also see the ones launched inside the containers.

I don't know how it's managed on other platforms. Anyway, even if running on other platforms, this article content will stay true.

Try software without pain

I will suppose from now that you already have installed on your computer. If this isn't already the case, I encourage you to do so.

Dockerhub

provides a public repository image/svg+xml hub where you can find virtually every piece of software you want to try at any version. For example, let's say you want to learn a new language, let's take :

You go to the image/svg+xml hub website, you put ocaml inside the search bar and you find ocaml/opam. If you go to the tag list page, you will see all the available versions and the OS list on which they are showcased. Let's choose this one:

Now, the goal is to create a folder on your host system (let's call it $ROOT), containing the code you will write to try things and use that folder inside docker to compile or run this code. Let's make the folder, and once it's done, open a terminal and go to this folder using cd. Now, run this command:

# On windows [powershell]
docker run -v"$PWD:/repo" -it ocaml/opam:debian-10-ocaml-4.06

# On linux [bash]
docker run -v"$PWD:/repo" -u"$(id -u):$(id -g)" -it ocaml/opam:debian-10-ocaml-4.06
# -u"$(id -u):$(id -g)" is to tell docker to launch the image as a user with
# the same user id and group id than your host user. This ensure all the files
# you create will be owned by your host user (and not root if you do not
# put the argument).

This command will start the image and mount our host directory $PWD (which is supposed to be $ROOT if you did well) to the container internal directory /repo (you could have chosen any name, but I recommend to not choose one among the linux standard directories like /usr, /lib, ..., otherwise you may encounter some troubles).

Then, let's install dune package, create a sample project and build it:

While still running the container, you can edit the files on your host system and build the project inside . Let's put this in $ROOT/helloworld/bin/main.ml:

let square x = x * x

let () = Printf.printf "square 4: %d\n" (square 4)

And now let's build and run again from inside of docker:

Conclusion

allows you to use complex environments without much pain. I didn't talk about it but you can even bind port from the inside of the container to the host. This can be useful if you're running an HTTP server from inside the container, for example, and want to expose it to a given the port on your host.