Containers

Contents

Containers#

Here is more carefull consideration of the options associated with working with containers.

import os
import docker
client = docker.from_env()

Run#

Here we look more closely at concepts related to running containers. See the relevant section in the official documentation.

Volumes#

There is a special parameter in docker.client.DockerClient - volumes. This allows you to specify volumes for your Docker container.

The definition of the volume has a specific syntax - it should be a dictionary, each element of which corresponds to the container. Each key is a path on the host, each value is another dictionary with keys bind and mode. Where bind is the path in the container and mode is the mode of the volume.

In general, it should look like this:

{
    "<path on the host 1>": {"bind": "<path on the container 1>", "mode": "<mode>"},
    "<path on the host 2>": {"bind": "<path on the container 2>", "mode": "<mode>"},
    ...
}

Consider example where we try to mount file to the container runned with sdk. So in the next file we creating file that contains specific message:

%%writefile containers_files/some_message
This is message from future container
Overwriting containers_files/some_message

This cell is running container and then executing cat some_message so content of the mounted file should be printed.

container = client.containers.run(
    image="ubuntu",
    name="temp_container",
    volumes={
        f"{os.getcwd()}/containers_files/some_message": 
        {'bind': '/some_message', 'mode': 'rw'}
    },
    detach=True,
    stdin_open=True,
    remove=True
)

print(container.exec_run("cat some_message").output.decode("utf-8"))

container.stop()
This is message from future container

Ports#

You can set ports for docker conatiner using the ports argument. It must take dict value with format {<port in the conatainer>: <port in the host>}.

Note: it can be confusing that in the docker run, -p parameter we usually set the port on the host first, but in the port argument of the docker SDK, the dictionary takes ports on the host as a keys.


The following cell starts the docker container with the ports argument.

container = client.containers.run(
    image="alpine",
    ports={6060: 7070},
    command="sh",
    detach=True,
    stdin_open=True,
    remove=True
)

The following code shows that the container was indeed created and that it has the appropriate ports configuration.

!docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS                                         NAMES
81bd3dacf36b   alpine    "sh"      3 seconds ago   Up 3 seconds   0.0.0.0:7070->6060/tcp, [::]:7070->6060/tcp   tender_allen
container.stop()

Logs#

You can get container logs as bytes by using logs() method.

The following example runs a Docker container that uses Python to spam some information to standard output.

command = """
    python3 -c 
    "for i in range(10): 
    print(''.join([chr(i+j+100) for j in range(10)]))"
"""
container = client.containers.run(
    "python:3.10.14-alpine3.20",
    command = command,
    detach = True
)

Now for an example of loading and printing logs from the container.

print(container.logs().decode("utf-8"))
container.remove()
defghijklm
efghijklmn
fghijklmno
ghijklmnop
hijklmnopq
ijklmnopqr
jklmnopqrs
klmnopqrst
lmnopqrstu
mnopqrstuv