.. include:: ../substitutions.txt
Working with Docker
===================
In this section, we will look at a few more advanced examples of working with
container images that are available on `Docker Hub `_.
We will run commands using the containerized assets both *interactively* and
*non-interactively*.
Pull An Official Image
----------------------
One powerful aspect of developing with containers and the Docker ecosystem is the
large collection of container images freely available. There are over 100,000
images on Docker Hub, but beware: using an image that you do not know anything
about comes with the same risks involved with running any software.
.. warning::
Be careful running container images that you are not familiar with. Some could contain
security vulnerabilities or, even worse, malicious code like viruses or ransomware.
To combat this, Docker Hub provides `"Official Images" `_,
a well-maintained set of container images providing high-quality installations of operating
systems, programming language environments and more.
We can search through the official images on Docker Hub `here `_.
Scroll down to find the Python official image called ``python``, then
click on that `image `_.
We see a lot of information about how to use the image, including information about the different
"tags" available. We see tags such as ``3.13-rc``, ``3.12.1``, ``3.12``, ``3``, etc.
We will discuss tags in detail later, but for now, does anyone have a guess as to what
the Python tags refer to?
We can pull the official Python image using command, then check to make sure it is
available locally:
.. code-block:: console
$ docker pull python
...
$ docker images
...
$ docker inspect python
...
.. tip::
Use ``docker inspect`` to find some metadata available for each image.
Start an Interactive Shell Inside a Container
---------------------------------------------
Using an interactive shell is a great way to poke around inside a container and
see what is in there. Imagine you are ssh-ing to a different Linux server, have
root access, and can see what files, commands, environment, etc., is available.
Before starting an interactive shell inside the container, execute the following
commands on your local device (we will see why in a minute):
.. code-block:: console
$ whoami
username
.. code-block:: console
$ pwd
/Users/username
.. include:: ../site_snippets/docker_local_uname.txt
Now start the interactive shell inside a Python container:
.. code-block:: console
$ docker run --rm -it python /bin/bash
root@fc5b620c5a88:/#
Here is an explanation of the command options:
.. code-block:: text
docker run # run a container
--rm # remove the container when we exit
-it # interactively attach terminal to inside of container
python # use the official python image
/bin/bash # execute the bash shell program inside container
Try the following commands - the same commands you did above before staring the
interactive shell in the container - and note what has changed:
.. code-block:: console
root@fc5b620c5a88:/# whoami
root
.. code-block:: console
root@fc5b620c5a88:/# pwd
/
.. code-block:: console
root@fc5b620c5a88:/# uname -a
Linux 8b1859f27f61 5.15.49-linuxkit-pr #1 SMP Thu May 25 07:17:40 UTC 2023 x86_64 GNU/Linux
Now you are the ``root`` user on a different operating system inside a running
Linux container! You can type ``exit`` to escape the container.
EXERCISE
~~~~~~~~
Before you exit the container, try running the command ``python``. What happens?
Compare that with running the command ``python`` directly on your local device.
Run a Command Inside a Container
--------------------------------
Back out on your local device, we now know we have a container image called
``python`` that has a particular version of Python (3.12.x) that may
not otherwise be available on your local device. The 3.12.x Python interpreter,
its standard library, and all of the dependencies of those are included in the
container image and are *isolated* from everything else. This image (``python``)
is portable and will run the exact same way on any OS that Docker supports,
assuming that image also supports the architecture.
In practice, though, we do not want to start interactive shells each time we need
to use a software application inside an image. Docker allows you to spin up an
*ad hoc* container to run applications from outside. For example, try:
.. code-block:: console
$ docker run --rm python whoami
root
.. code-block:: console
$ docker run --rm python pwd
/
.. code-block:: console
$ docker run --rm python uname -a
Linux 8b1859f27f61 5.15.49-linuxkit-pr #1 SMP Thu May 25 07:17:40 UTC 2023 x86_64 GNU/Linux
.. code-block:: console
$ docker run -it --rm python
Python 3.12.1 (main, Jan 17 2024, 06:18:08) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
The first three commands above omitted the ``-it`` flags because they did not
require an interactive terminal to run. On each of these commands, Docker finds
the image the command refers to, spins up a new container based on that image,
executes the given command inside, prints the result, and exits and removes the
container.
The last command, which did not specify a command to run inside the container, uses the container's
default command. We do not know ahead of time what (if any) default command is provided for
any given image, but what default command was provided for the ``python`` image?
Yes, it was the ``python`` command itself, and that requires an interactivity to use,
so we provide the ``-it`` flags.
If all else fails, display the help text:
.. code-block:: console
$ docker --help
shows all docker options and summaries
.. code-block:: console
$ docker COMMAND --help
shows options and summaries for a particular command
Additional Resources
--------------------
* `Docker Docs `_
* `Best Practices for Writing Dockerfiles `_
* `Docker Hub `_
* `Docker for Beginners `_
* `Play with Docker `_