Part 1

Interacting with the container via volumes and ports

We can use volumes to make it easier to store the downloads outside the containers ephemeral storage. With bind mount we can mount a file or directory from our own machine into the container. Let's start another container with -v option, that requires an absolute path. We mount our current folder as /mydir in our container, overwriting everything that we have put in that folder in our Dockerfile.

$ docker run -v "$(pwd):/mydir" youtube-dl https://imgur.com/JY5tHqr

So a volume is simply a folder (or a file) that is shared between the host machine and the container. If a file in volume is modified by a program that's running inside the container the changes are also saved from destruction when the container is shut down as the file exists on the host machine. This is the main use for volumes as otherwise all of the files wouldn't be accessible when restarting the container. Volumes also can be used to share files between containers and run programs that are able to load changed files.

In our youtube-dl we wanted to mount the whole directory since the files are fairly randomly named. If we wish to create a volume with only a single file we could also do that by pointing to it. For example -v $(pwd)/material.md:/mydir/material.md this way we could edit the material.md locally and have it change in the container (and vice versa). Note also that -v creates a directory if the file does not exist.

Allowing external connections into containers

The details on how programs communicate are not detailed in this course. Courses on Operating Systems and the Networking courses explain subjects in detail. In this course you only need to know the following simplified basics:

  • Sending messages: Programs can send messages to URL addresses such as this: http://127.0.0.1:3000 where http is the protocol, 127.0.0.1 is a ip address, and and 3000 is a port. Note the ip part could also be a hostname: 127.0.0.1 is also called localhost so instead you could use http://localhost:3000.

  • Receiving messages: Programs can be assigned to listen to any available port. If a program is listening for traffic on port 3000, and a message is sent to that port, it will receive it (and possibly process it).

The address 127.0.0.1 and hostname localhost are special ones, they refer to the machine or container itself, so if you are on a container and send message to localhost, the target is the same container. Similarly, if you are sending the request from outside of a container to localhost, the target is your machine.

You can map your host machine port to a container port.

Opening a connection from outside world to a docker container happens in two steps:

  • Exposing port

  • Publishing port

Exposing a container port means telling Docker that the container listens to a certain port. This doesn't do much, except it helps humans with the configuration.

Publishing a port means that Docker will map host ports to the container ports.

To expose a port, add the line EXPOSE <port> in your Dockerfile

To publish a port, run the container with -p <host-port>:<container-port>

If you leave out the host port and only specify the container port, docker will automatically choose a free port as the host port:

$ docker run -p 4567 app-in-port

We could also limit connections to certain protocol only, e.g. udp by adding the protocol at the end: EXPOSE <port>/udp and -p <host-port>:<container-port>/udp.

You have reached the end of this section! Continue to the next section: