diff --git a/config.yaml b/config.yaml index 7b7b14f69..216fe19ad 100644 --- a/config.yaml +++ b/config.yaml @@ -11,7 +11,7 @@ carpentry: 'incubator' # Overall title for pages. -title: 'Reproducible Computational Environments Using Containers: Introduction to Docker' +title: 'Reproducible Computational Environments Using Containers: Introduction to Podman' # Date the lesson was created (YYYY-MM-DD, this is empty by default) created: @@ -60,7 +60,7 @@ contact: 'docker-introduction+admins@lists.carpentries.org' # Order of episodes in your lesson episodes: - introduction.md -- meet-docker.md +- meet-podman.md - running-containers.md - managing-containers.md - docker-hub.md diff --git a/episodes/advanced-containers.md b/episodes/advanced-containers.md index 58ace8986..f8627e89b 100644 --- a/episodes/advanced-containers.md +++ b/episodes/advanced-containers.md @@ -6,8 +6,8 @@ exercises: 30 ::::::::::::::::::::::::::::::::::::::: objectives -- Explain how you can include files within Docker container images when you build them. -- Explain how you can access files on the Docker host from your Docker containers. +- Explain how you can include files within container images when you build them. +- Explain how you can access files on the host from your containers. :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -16,7 +16,7 @@ exercises: 30 - How can I add local files (e.g. data files) into container images at build time? -- How can I access files stored on the host system from within a running Docker +- How can I access files stored on the host system from within a running Podman container? :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -34,11 +34,11 @@ using the first 1--2 sections on this page. ## Using scripts and files from outside the container -In your shell, change to the `sum` folder in the `docker-intro` folder and look at +In your shell, change to the `sum` folder in the `podman-intro` folder and look at the files inside. ```bash -$ cd ~/Desktop/docker-intro/sum +$ cd ~/Desktop/podman-intro/sum $ ls ``` @@ -60,7 +60,7 @@ Question: What command would we use to run Python from the `alpine-python` conta We can run a container from the alpine-python container image using: ```bash -$ docker container run alice/alpine-python +$ podman container run alice/alpine-python python3 sum.py ``` What happens? Since the `Dockerfile` that we built this container image from @@ -69,16 +69,16 @@ command simply starts a container from the image, runs the `python3 --version` command and exits. You should have seen the installed version of Python printed to the terminal. -Instead, if we want to run an interactive Python terminal, we can use `docker +Instead, if we want to run an interactive Python terminal, we can use `podman container run` to override the default run command embedded within the container image. So we could run: ```bash -$ docker container run -it alice/alpine-python python3 +$ podman container run -it alice/alpine-python python3 ``` -The `-it` tells Docker to set up and interactive terminal connection to the -running container, and then we're telling Docker to run the `python3` command +The `-it` tells Podman to set up and interactive terminal connection to the +running container, and then we're telling Podman to run the `python3` command inside the container which gives us an interactive Python interpreter prompt. _(type `exit()` to exit!)_ @@ -89,7 +89,7 @@ _(type `exit()` to exit!)_ If we try running the container and Python script, what happens? ```bash -$ docker container run alice/alpine-python python3 sum.py +$ podman container run alice/alpine-python python3 sum.py ``` ```output @@ -119,7 +119,7 @@ or other external hard drive gets connected to a computer -- you can see the contents appear as if they were on your computer. We can create a mount between our computer and the running container by using an additional -option to `docker container run`. We'll also use the variable `${PWD}` which will substitute +option to `podman container run`. We'll also use the variable `${PWD}` which will substitute in our current working directory. The option will look like this `--mount type=bind,source=${PWD},target=/temp` @@ -133,10 +133,11 @@ directory `/temp` -- the target. ## Types of mounts You will notice that we set the mount `type=bind`, there are other types of mount that -can be used in Docker (e.g. `volume` and `tmpfs`). We do not cover other types of mounts +can be used in Podman (e.g. `volume` and `tmpfs`). We do not cover other types of mounts or the differences between these mount types in the course as it is more of an advanced topic. You can find more information on the different mount types in -[the Docker documentation](https://docs.docker.com/storage/). +[the Docker documentation](https://docs.docker.com/storage/) and how to use them in +[the Podman documentation](https://docs.podman.io/en/latest/markdown/podman-run.1.html#mount-type-type-type-specific-option). :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -144,7 +145,7 @@ topic. You can find more information on the different mount types in Let's try running the command now: ```bash -$ docker container run --mount type=bind,source=${PWD},target=/temp alice/alpine-python python3 sum.py +$ podman container run --mount type=bind,source=${PWD},target=/temp alice/alpine-python python3 sum.py ``` But we get the same error! @@ -159,7 +160,7 @@ mapped to `/temp` -- so we need to include that in the path to the script. This command should give us what we need: ```bash -$ docker container run --mount type=bind,source=${PWD},target=/temp alice/alpine-python python3 /temp/sum.py +$ podman container run --mount type=bind,source=${PWD},target=/temp alice/alpine-python python3 /temp/sum.py ``` Note that if we create any files in the `/temp` directory while the container is @@ -168,19 +169,20 @@ and will stay there even when the container stops. ::::::::::::::::::::::::::::::::::::::::: callout -## Other Commonly Used Docker Run Flags +## Other Commonly Used Podman Run Flags -Docker run has many other useful flags to alter its function. +Podman run has many other useful flags to alter its function. A couple that are commonly used include `-w` and `-u`. The `--workdir`/`-w` flag sets the working directory a.k.a. runs the command being executed inside the directory specified. For example, the following code would run the `pwd` command in a container -started from the latest ubuntu image in the `/home/alice` directory and print -`/home/alice`. If the directory doesn't exist in the image it will create it. +started from the latest ubuntu image in the `/home/ubuntu` directory and print +`/home/ubuntu`. Podman requires the working directory specified to already +exist in the image. ``` -docker container run -w /home/alice/ ubuntu pwd +podman container run -w /home/ubuntu/ ubuntu pwd ``` The `--user`/`-u` flag lets you specify the username you would like to run the @@ -195,7 +197,7 @@ fetch the current user's ID and group and run the container as that user. ## Exercise: Explore the script -What happens if you use the `docker container run` command above +What happens if you use the `podman container run` command above to sun `sum.py` and put numbers after the script name? ::::::::::::::: solution @@ -216,9 +218,9 @@ that are passed to it as arguments. ## Exercise: Checking the options -Our Docker command has gotten much longer! Can you go through each piece of -the Docker command above and explain what it does? How would you characterize -the key components of a Docker command? +Our Podman command has gotten much longer! Can you go through each piece of +the Podman command above and explain what it does? How would you characterize +the key components of a Podman command? ::::::::::::::: solution @@ -226,14 +228,14 @@ the key components of a Docker command? Here's a breakdown of each piece of the command above -- `docker container run`: use Docker to run a container +- `podman container run`: use Podman to run a container - `--mount type=bind,source=${PWD},target=/temp`: connect my current working directory (`${PWD}`) as a folder inside the container called `/temp` - `alice/alpine-python`: name of the container image to use to run the container - `python3 /temp/sum.py`: what commands to run in the container -More generally, every Docker command will have the form: -`docker [action] [docker options] [docker container image] [command to run inside]` +More generally, every Podman command will have the form: +`podman [action] [podman options] [podman container image] [command to run inside]` ::::::::::::::::::::::::: @@ -250,14 +252,14 @@ Can you find the folder that's connected to your host computer? What's inside? ## Solution -The docker command to run the container interactively is: +The Podman command to run the container interactively is: ```bash -$ docker container run --mount type=bind,source=${PWD},target=/temp -it alice/alpine-python sh +$ podman container run --mount type=bind,source=${PWD},target=/temp -it alice/alpine-python sh ``` Once inside, you should be able to navigate to the `/temp` folder -and see that's contents are the same as the files on your host computer: +and see that its contents are the same as the files on your host computer: ```bash /# cd /temp @@ -278,14 +280,14 @@ might want to do if you're sharing a finished analysis or just want to have an archived copy of your entire analysis including the data. Let's assume that we've finished with our `sum.py` script and want to add it to the container image itself. -In your shell, you should still be in the `sum` folder in the `docker-intro` folder. +In your shell, you should still be in the `sum` folder in the `podman-intro` folder. ```bash $ pwd ``` ```bash -$ /Users/yourname/Desktop/docker-intro/sum +$ /Users/yourname/Desktop/podman-intro/sum ``` Let's add a new line to the `Dockerfile` we've been using so far to create a copy of `sum.py`. @@ -295,25 +297,25 @@ We can do so by using the `COPY` keyword. COPY sum.py /home ``` -This line will cause Docker to copy the file from your computer into the container's +This line will cause Podman to copy the file from your computer into the container's filesystem. Let's build the container image like before, but give it a different name: ```bash -$ docker image build -t alice/alpine-sum . +$ podman image build -t alice/alpine-sum . ``` ::::::::::::::::::::::::::::::::::::::::: callout ## The Importance of Command Order in a Dockerfile -When you run `docker image build` it executes the build in the order specified +When you run `podman image build` it executes the build in the order specified in the `Dockerfile`. This order is important for rebuilding and you typically will want to put your `RUN` commands before your `COPY` commands. -Docker builds the layers of commands in order. +Podman builds the layers of commands in order. This becomes important when you need to rebuild container images. -If you change layers later in the `Dockerfile` and rebuild the container image, Docker doesn't need to +If you change layers later in the `Dockerfile` and rebuild the container image, Podman doesn't need to rebuild the earlier layers but will instead used a stored (called "cached") version of those layers. @@ -339,7 +341,7 @@ Once inside, try running the Python script. You can start the container interactively like so: ```bash -$ docker container run -it alice/alpine-sum sh +$ podman container run -it alice/alpine-sum sh ``` You should be able to run the python command inside the container like this: @@ -357,7 +359,7 @@ that you want to publish or use as a record. Note that it's not necessarily a go to put your scripts inside the container image if you're constantly changing or editing them. Then, referencing the scripts from outside the container is a good idea, as we did in the previous section. You also want to think carefully about size -- if you -run `docker image ls` you'll see the size of each container image all the way on the right of +run `podman image ls` you'll see the size of each container image all the way on the right of the screen. The bigger your container image becomes, the harder it will be to easily download. ::::::::::::::::::::::::::::::::::::::::: callout @@ -417,8 +419,8 @@ CMD ["python3", "/home/sum.py"] Build and test it: ```bash -$ docker image build -t alpine-sum:v1 . -$ docker container run alpine-sum:v1 +$ podman image build -t alpine-sum:v1 . +$ podman container run alpine-sum:v1 ``` You'll notice that you can run the container without arguments just fine, @@ -426,15 +428,15 @@ resulting in `sum = 0`, but this is boring. Supplying arguments however doesn't work: ```bash -docker container run alpine-sum:v1 10 11 12 +podman container run alpine-sum:v1 10 11 12 ``` results in ```output -docker: Error response from daemon: OCI runtime create failed: -container_linux.go:349: starting container process caused "exec: -\"10\": executable file not found in $PATH": unknown. +Error: preparing container 8444a537a847f5b4d75a56fec767bfaf59a6f417277c36c0e46422f12c4fe01d for attach: +crun: executable file `10` not found in $PATH: +No such file or directory: OCI runtime attempted to invoke a command that was not found ``` This is because the arguments `10 11 12` are interpreted as a @@ -462,11 +464,11 @@ CMD ["10", "11"] Build and test it: ```bash -$ docker image build -t alpine-sum:v2 . +$ podman image build -t alpine-sum:v2 . # Most of the time you are interested in the sum of 10 and 11: -$ docker container run alpine-sum:v2 +$ podman container run alpine-sum:v2 # Sometimes you have more challenging calculations to do: -$ docker container run alpine-sum:v2 12 13 14 +$ podman container run alpine-sum:v2 12 13 14 ``` ::::::::::::::::::::::::::::::::::::::::: callout @@ -479,7 +481,7 @@ that does only sums, but you need an interactive shell to examine the container: ```bash -$ docker container run -it alpine-sum:v2 /bin/sh +$ podman container run -it alpine-sum:v2 /bin/sh ``` will yield @@ -491,7 +493,7 @@ Please supply integer arguments You need to override the `ENTRYPOINT` statement in the container image like so: ```bash -$ docker container run -it --entrypoint /bin/sh alpine-sum:v2 +$ podman container run -it --entrypoint /bin/sh alpine-sum:v2 ``` :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -513,8 +515,8 @@ ENV PATH /home:$PATH Build and test it: ```bash -$ docker image build -t alpine-sum:v3 . -$ docker container run alpine-sum:v3 sum.py 1 2 3 4 +$ podman image build -t alpine-sum:v3 . +$ podman container run alpine-sum:v3 sum.py 1 2 3 4 ``` ::::::::::::::::::::::::::::::::::::::::: callout @@ -535,8 +537,8 @@ demonstrating how the rules highlighted by the paper can be applied. :::::::::::::::::::::::::::::::::::::::: keypoints -- Docker allows containers to read and write files from the Docker host. -- You can include files from your Docker host into your Docker container images by using the `COPY` instruction in your `Dockerfile`. +- Podman allows containers to read and write files from the Podman host. +- You can include files from your Podman host into your container images by using the `COPY` instruction in your `Dockerfile`. :::::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/episodes/creating-container-images.md b/episodes/creating-container-images.md index cf8f7b62f..aa5da8494 100644 --- a/episodes/creating-container-images.md +++ b/episodes/creating-container-images.md @@ -7,7 +7,7 @@ exercises: 15 ::::::::::::::::::::::::::::::::::::::: objectives - Explain the purpose of a `Dockerfile` and show some simple examples. -- Demonstrate how to build a Docker container image from a `Dockerfile`. +- Demonstrate how to build a container image with Podman from a `Dockerfile`. - Compare the steps of creating a container image interactively versus a `Dockerfile`. - Create an installation strategy for a container image. - Demonstrate how to upload ('push') your container images to the Docker Hub. @@ -17,14 +17,14 @@ exercises: 15 :::::::::::::::::::::::::::::::::::::::: questions -- How can I make my own Docker container images? -- How do I document the 'recipe' for a Docker container image? +- How can I make my own container images with Podman? +- How do I document the 'recipe' for a container image? :::::::::::::::::::::::::::::::::::::::::::::::::: -There are lots of reasons why you might want to create your **own** Docker container image. +There are lots of reasons why you might want to create your **own** container image. -- You can't find a container image with all the tools you need on Docker Hub. +- You can't find a container image with all the tools you need on Docker Hub or elsewhere. - You want to have a container image to "archive" all the specific software versions you ran for a project. - You want to share your workflow with someone else. @@ -34,7 +34,7 @@ Before creating a reproducible installation, let's experiment with installing software inside a container. Start a container from the `alpine` container image we used before, interactively: ```bash -$ docker container run -it alpine sh +$ podman container run -it alpine sh ``` Because this is a basic container, there's a lot of things not installed -- for @@ -98,11 +98,26 @@ If you haven't already, exit out of the interactively running container. A `Dockerfile` is a plain text file with keywords and commands that can be used to create a new container image. +::::::::::::::::::::::::::::::::::::::::: callout + +## Dockerfiles and Containerfiles + +You may see references on the Internet and in documentation to both +`Dockerfile`s and `Containerfile`s. The two are essentially identical, +differing only in the file name used, and Podman is capable of using both. Due +to Docker's historical prominence it is very common for the `Dockerfile` name +to be used even in contexts which don't use Docker, and we will do so here +also -- but remember that there is no problem with using the alternate +`Containerfile` name. + + +:::::::::::::::::::::::::::::::::::::::::::::::::: + From your shell, go to the folder you downloaded at the start of the lesson and print out the Dockerfile inside: ```bash -$ cd ~/Desktop/docker-intro/basic +$ cd ~/Desktop/podman-intro/basic $ cat Dockerfile ``` @@ -120,8 +135,8 @@ Let's break this file down: - The last line, `CMD`, indicates the default command we want a container based on this container image to run, if no other command is provided. It is recommended to provide `CMD` in *exec-form* (see the - [`CMD` section](https://docs.docker.com/engine/reference/builder/#cmd) - of the Dockerfile documentation for more details). It is written as a + (see the [`CMD` section](https://github.com/containers/common/blob/main/docs/Containerfile.5.md) + of the documentation of the Containers GitHub for more details). It is written as a list which contains the executable to run as its first element, optionally followed by any arguments as subsequent elements. The list is enclosed in square brackets (`[]`) and its elements are @@ -134,10 +149,11 @@ Let's break this file down: ## *shell-form* and *exec-form* for CMD Another way to specify the parameter for the -[`CMD` instruction](https://docs.docker.com/engine/reference/builder/#cmd) +[`CMD` instruction](https://github.com/containers/common/blob/main/docs/Containerfile.5.md) is the *shell-form*. Here you type the command as you would call it -from the command line. Docker then silently runs this command in the -image's standard shell. `CMD cat /etc/passwd` is equivalent to `CMD ["/bin/sh", "-c", "cat /etc/passwd"]`. We recommend to prefer the +from the command line. Podman then silently runs this command in the +image's standard shell. The *shell-form* `CMD cat /etc/passwd` is equivalent to +the *exec-form* `CMD ["/bin/sh", "-c", "cat /etc/passwd"]`. We recommend the more explicit *exec-form* because we will be able to create more flexible container image command options and make sure complex commands are unambiguous in this format. @@ -160,7 +176,7 @@ Based on our experience above, edit the `Dockerfile` (in your text editor of cho to look like this: ``` -FROM alpine +FROM docker.io/alpine RUN apk add --update python3 py3-pip python3-dev CMD ["python3", "--version"] ``` @@ -173,15 +189,15 @@ The recipe provided by the `Dockerfile` shown in the solution to the preceding e add Python 3, the pip package management tool and some additional Python header files, and set a default command to request Python 3 to report its version information. -## Create a new Docker image +## Create a new container image So far, we only have a text file named `Dockerfile` -- we do not yet have a container image. -We want Docker to take this `Dockerfile`, +We want Podman to take this `Dockerfile`, run the installation commands contained within it, and then save the resulting container as a new container image. To do this we will use the -`docker image build` command. +`podman image build` command. -We have to provide `docker image build` with two pieces of information: +We have to provide `podman image build` with two pieces of information: - the location of the `Dockerfile` - the name of the new container image. Remember the naming scheme from before? You should name @@ -190,32 +206,36 @@ We have to provide `docker image build` with two pieces of information: All together, the build command that you should run on your computer, will have a similar structure to this: ```bash -$ docker image build -t USERNAME/CONTAINER_IMAGE_NAME . +$ podman image build -t URL/USERNAME/CONTAINER_IMAGE_NAME . ``` The `-t` option names the container image; the final dot indicates that the `Dockerfile` is in our current directory. -For example, if my user name was `alice` and I wanted to call my -container image `alpine-python`, I would use this command: +The `URL` should be the name of the registry you are intending to upload the +image to. If you aren't intending to ever move the image elsewhere, you can skip +it and only give the `USERNAME` and `CONTAINER_IMAGE_NAME`. For example, if I +were intending to push the image to Docker Hub, my Docker Hub user name was +`alice` and I wanted to call my container image `alpine-python`, I would use +this command: ```bash -$ docker image build -t alice/alpine-python . +$ podman image build -t docker.io/alice/alpine-python . ``` ::::::::::::::::::::::::::::::::::::::::: callout ## Build Context -Notice that the final input to `docker image build` isn't the Dockerfile -- it's +Notice that the final input to `podman image build` isn't the Dockerfile -- it's a directory! In the command above, we've used the current working directory (`.`) of -the shell as the final input to the `docker image build` command. This option provides -what is called the *build context* to Docker -- if there are files being copied -into the built container image [more details in the next episode](advanced-containers.md) -they're assumed to be in this location. Docker expects to see a Dockerfile in the +the shell as the final input to the `podman image build` command. This option provides +what is called the *build context* to Podman -- if there are files being copied +into the built container image ([more details in the next episode](advanced-containers.md)) +they're assumed to be in this location. Podman expects to see a Dockerfile in the build context also (unless you tell it to look elsewhere). -Even if it won't need all of the files in the build context directory, Docker does +Even if it won't need all of the files in the build context directory, Podman does "load" them before starting to build, which means that it's a good idea to have only what you need for the container image in a build context directory, as we've done in this example. @@ -230,35 +250,36 @@ in this example. 1. Think back to earlier. What command can you run to check if your container image was created successfully? (Hint: what command shows the container images on your computer?) -2. We didn't specify a tag for our container image name. What tag did Docker automatically use? +2. We didn't specify a tag for our container image name. What tag did Podman automatically use? 3. What command will run a container based on the container image you've created? What should happen by default - if you run such a container? Can you make it do something different, like print + if you run such a container? Without changing the Dockerfile, can you make it do something different, like print "hello world"? ::::::::::::::: solution ## Solution -1. To see your new image, run `docker image ls`. You should see the name of your new - container image under the "REPOSITORY" heading. +1. To see your new image, run `podman image ls`. You should see the name of your new + container image under the "REPOSITORY" heading, , prepended by `localhost` as, for now, + the image is on your local machine rather than a remote registry. -2. In the output of `docker image ls`, you can see that Docker has automatically +2. In the output of `podman image ls`, you can see that Podman has automatically used the `latest` tag for our new container image. -3. We want to use `docker container run` to run a container based on a container image. +3. We want to use `podman container run` to run a container based on a container image. The following command should run a container and print out our default message, the version of Python: ```bash -$ docker container run alice/alpine-python +$ podman container run docker.io/alice/alpine-python ``` To run a container based on our container image and print out "Hello world" instead: ```bash -$ docker container run alice/alpine-python echo "Hello World" +$ podman container run docker.io/alice/alpine-python echo "Hello World" ``` ::::::::::::::::::::::::: @@ -278,7 +299,7 @@ Here are some things to consider when creating your own container image: [R programming language](https://hub.docker.com/r/rocker/r-ver/). We've used Alpine Linux as an example in this lesson, but it's generally not a good container image to start with for initial development and experimentation because it is - a less common distribution of Linux; using [Ubuntu](https://hub.docker.com/_/ubuntu), [Debian](https://hub.docker.com/_/debian) and [CentOS](https://hub.docker.com/_/centos) are all + a less common distribution of Linux; using [Ubuntu](https://hub.docker.com/_/ubuntu), [Debian](https://hub.docker.com/_/debian) and [Alma](https://hub.docker.com/_/almalinux) are all good options for scientific software installations. The program you're using might recommend a particular distribution of Linux, and if so, it may be useful to start with a container image for that distribution. - **How big?** How much software do you really need to install? When you have a choice, @@ -287,7 +308,8 @@ Here are some things to consider when creating your own container image: - **Know (or Google) your Linux**. Different distributions of Linux often have distinct sets of tools for installing software. The `apk` command we used above is the software package installer for Alpine Linux. The installers for various common Linux distributions are listed below: - Ubuntu: `apt` or `apt-get` - Debian: `deb` - - CentOS: `yum` + - Alma/Rocky/Fedora: `dnf` + - SUSE: `zypper` Most common software installations are available to be installed via these tools. A web search for "install X on Y Linux" is usually a good start for common software installation tasks; if something isn't available via the Linux distribution's installation @@ -312,10 +334,10 @@ In general, a good strategy for installing software is: Container images that you release publicly can be stored on the Docker Hub for free. If you name your container image as described above, with your Docker Hub username, all you need to do -is run the opposite of `docker image pull` -- `docker image push`. +is run the opposite of `podman image pull` -- `podman image push`. ```bash -$ docker image push alice/alpine-python +$ podman image push docker.io/alice/alpine-python ``` Make sure to substitute the full name of your container image! @@ -326,40 +348,43 @@ In a web browser, open [https://hub.docker.com](https://hub.docker.com), and on ## Logging In -Technically, you have to be logged into Docker on your computer for this to work. -Usually it happens by default, but if `docker image push` doesn't work for you, -run `docker login` first, enter your Docker Hub username and password, and then -try `docker image push` again. +Technically, you have to be logged into Docker Hub with Podman on your computer +for this to work. If you haven't yet done this, `podman image push` won't work +for you. You can do this on the command line by running `podman login docker.io` +first, entering your Docker Hub username and password, and then trying `podman +image push` again. If you installed Podman via Podman Desktop, you can also log +in with the GUI by opening Podman Desktop, then going to 'Settings', then +'Registries', then clicking 'Configure' for the Docker Hub entry. :::::::::::::::::::::::::::::::::::::::::::::::::: ## What's in a name? (again) -You don't *have* to name your containers images using the `USERNAME/CONTAINER_IMAGE_NAME:TAG` naming scheme. On your own computer, you can call container images whatever you want, and refer to +You don't *have* to name your containers images using the `URL/USERNAME/CONTAINER_IMAGE_NAME:TAG` naming scheme. On your own computer, you can call container images whatever you want, and refer to them by the names you choose. It's only when you want to share a container image that it needs the correct naming format. -You can rename container images using the `docker image tag` command. For example, imagine someone +You can rename container images using the `podman image tag` command. For example, imagine someone named Alice has been working on a workflow container image and called it `workflow-test` on her own computer. She now wants to share it in her `alice` Docker Hub account -with the name `workflow-complete` and a tag of `v1`. Her `docker image tag` command +with the name `workflow-complete` and a tag of `v1`. Her `podman image tag` command would look like this: ```bash -$ docker image tag workflow-test alice/workflow-complete:v1 +$ podman image tag workflow-test docker.io/alice/workflow-complete:v1 ``` She could then push the re-named container image to Docker Hub, -using `docker image push alice/workflow-complete:v1` +using `podman image push docker.io/alice/workflow-complete:v1` :::::::::::::::::::::::::::::::::::::::: keypoints -- `Dockerfile`s specify what is within Docker container images. -- The `docker image build` command is used to build a container image from a `Dockerfile`. -- You can share your Docker container images through the Docker Hub so that others can create Docker containers from your container images. +- `Dockerfile`s specify what is within container images. +- The `podman image build` command is used to build a container image from a `Dockerfile`. +- You can share your container images through the Docker Hub so that others can create containers from your container images. :::::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/episodes/docker-hub.md b/episodes/docker-hub.md index 17b17adb8..be38e3a26 100644 --- a/episodes/docker-hub.md +++ b/episodes/docker-hub.md @@ -1,5 +1,5 @@ --- -title: Finding Containers on Docker Hub +title: Finding Containers on a Registry teaching: 10 exercises: 10 --- @@ -7,8 +7,8 @@ exercises: 10 ::::::::::::::::::::::::::::::::::::::: objectives - Understand the importance of container registries such as Docker Hub, quay.io, etc. -- Explore the Docker Hub webpage for a popular Docker container image. -- Find the list of tags for a particular Docker container image. +- Explore the Docker Hub webpage for a popular container image. +- Find the list of tags for a particular container image. - Identify the three components of a container image's identifier. :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -27,11 +27,13 @@ and maybe `ubuntu`. Where did these container images come from? The Docker Hub! The Docker Hub is an online repository of container images, a vast number of which are publicly available. A large number of the container images are curated by the developers of the software that they package. Also, many commonly used pieces of software that have been containerized into images are officially endorsed, which means that you can trust the container images to have been checked for functionality, stability, and that they don't contain malware. +Other registries do exist. If Podman is used to pull the `hello-world` image with no further information, as we did earlier, it will be retrieved from [Quay](https://quay.io/). Other popular registries are [Harbor](https://goharbor.io/) and the GitHub Container Registry . It is also possible to set up a local registry using Podman itself or products like Harbor or Quay. These may be specialised for use by a particular organisation. + ::::::::::::::::::::::::::::::::::::::::: callout -## Docker can be used without connecting to the Docker Hub +## Podman can be used without connecting to the Docker Hub -Note that while the Docker Hub is well integrated into Docker functionality, the Docker Hub is certainly not required for all types of use of Docker containers. For example, some organizations may run container infrastructure that is entirely disconnected from the Internet. +Note that while the Docker Hub is well integrated into Podman functionality, the Docker Hub is certainly not required for all types of use of containers. For example, some organizations may run container infrastructure that is entirely disconnected from the Internet. :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -54,9 +56,20 @@ The main body of the page contains many used headings, such as: The "How to use the image" section of most container images' pages will provide examples that are likely to cover your intended use of the container image. +::::::::::::::::::::::::::::::::::::::::: callout + +## Other container registries + +If you look at another registry, you will probably find that similar information +is made available by the container's maintainer. They may even mirror what you +see on other registries; for example, here is the [Python +image's](https://quay.io/repository/lib/python) page on Quay. + +:::::::::::::::::::::::::::::::::::::::::::::::::: + ## Exploring Container Image Versions -A single Docker Hub page can have many different versions of container images, +Registries will often provide many different versions of container images, based on the version of the software inside. These versions are indicated by "tags". When referring to the specific version of a container image by its tag, you use a colon, `:`, like this: @@ -65,16 +78,17 @@ by its tag, you use a colon, `:`, like this: CONTAINER_IMAGE_NAME:TAG ``` -So if I wanted to download the `python` container image, with Python 3.8, I would use this name: +So if I wanted to download the `python` container image, with Python 3.8, I would use this name. To specifically +pull the Python 3.8 image from Docker Hub, you would then use the following Podman command: ```bash -$ docker image pull python:3.8 +$ podman image pull python:3.8 ``` But if I wanted to download a Python 3.6 container image, I would use this name: ```bash -$ docker image pull python:3.6 +$ podman image pull python:3.6 ``` The default tag (which is used if you don't specify one) is called `latest`. @@ -107,16 +121,41 @@ OWNER/REPOSITORY:TAG :::::::::::::::::::::::::::::::::::::::::::::::::: +::::::::::::::::::::::::::::::::::::::::: callout + +## Registry URLs + +For almost all repositories, Podman will by default look for them and download +them from Docker Hub. This means that if you want a container from a different +registry, you will need to tell it to do so by providing the registry's URL. +This is prepended to the shorter names we've been using so far, to give a fully +qualified name of the form + +``` +URL/OWNER/REPOSITORY:TAG +``` + +Public registries often have `.io` URLs, so we would use `docker.io` for Docker Hub, +`ghcr.io` for the GitHub Container Registry, or `quay.io` for Quay. It is often +preferable to provide to fully qualified name to prevent registry resolution +errors, and to be sure that you're pulling the container you think you are. +Ultimately, the fully qualified form of a Docker Hub-hosted image is: +``` +docker.io/OWNER/REPOSITORY:TAG +``` + +:::::::::::::::::::::::::::::::::::::::::::::::::: + ::::::::::::::::::::::::::::::::::::::: challenge ## What's in a name? -How would I download the Docker container image produced by the `rocker` group that +How would I download the Docker Hub container image produced by the `rocker` group that has version 3.6.1 of R and the tidyverse installed? Note: the container image described in this exercise is large and won't be used later in this lesson, so you don't actually need to pull the container image -- -constructing the correct `docker pull` command is sufficient. +constructing the correct `podman pull` command is sufficient. ::::::::::::::: solution @@ -127,7 +166,7 @@ You can look at the list of tags, or just guess that the tag is `3.6.1`. Altoget that means that the name of the container image we want to download is: ```bash -$ docker image pull rocker/tidyverse:3.6.1 +$ podman image pull docker.io/rocker/tidyverse:3.6.1 ``` ::::::::::::::::::::::::: @@ -155,13 +194,14 @@ functional and secure: If a container image is never updated, created by a random person, and does not have a lot of metadata, it is probably worth skipping over. Even if such a container image is secure, it -is not reproducible and not a dependable way to run research computations. +is not reproducible and not a dependable way to run research computations. You can apply +these considerations to any open container registry you use. ::::::::::::::::::::::::::::::::::::::: challenge ## What container image is right for you? -Find a Docker container image that's relevant to you. Take into account the suggestions +Find a container image that's relevant to you. Take into account the suggestions above of what to look for as you evaluate options. If you're unsuccessful in your search, or don't know what to look for, you can use the R or Python container image we've already seen. @@ -179,11 +219,12 @@ the container image and explore it. :::::::::::::::::::::::::::::::::::::::: keypoints -- The Docker Hub is an online repository of container images. +- A container registry is an online repository of container images. +- "Docker Hub is the most widely used container registry." - Many Docker Hub container images are public, and may be officially endorsed. - Each Docker Hub page about a container image provides structured information and subheadings - Most Docker Hub pages about container images contain sections that provide examples of how to use those container images. - Many Docker Hub container images have multiple versions, indicated by tags. -- The naming convention for Docker container images is: `OWNER/CONTAINER_IMAGE_NAME:TAG` +- The naming convention for Docker container images when using Podman is: `docker.io/OWNER/CONTAINER_IMAGE_NAME:TAG` :::::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/episodes/files/docker-intro.zip b/episodes/files/docker-intro.zip deleted file mode 100644 index 2ddd9bc73..000000000 Binary files a/episodes/files/docker-intro.zip and /dev/null differ diff --git a/episodes/files/podman-intro.zip b/episodes/files/podman-intro.zip new file mode 100644 index 000000000..eec324452 Binary files /dev/null and b/episodes/files/podman-intro.zip differ diff --git a/episodes/introduction.md b/episodes/introduction.md index b2a5ada2a..36fc83beb 100644 --- a/episodes/introduction.md +++ b/episodes/introduction.md @@ -21,10 +21,10 @@ exercises: 5 ::::::::::::::::::::::::::::::::::::::::: callout -## Learning about Docker Containers +## Learning about software containers The Australian Research Data Commons has produced a short introductory video -about Docker containers that covers many of the points below. Watch it before +about containers that covers many of the points below. Watch it before or after you go through this section to reinforce your understanding! [How can software containers help your research?](https://www.youtube.com/watch?v=HelrQnm3v4g) @@ -137,9 +137,9 @@ flavour of Linux + the filesystem inside. :::::::::::::::::::::::::::::::::::::::::::::::::: -## What is Docker? +## What is Podman? -[Docker][Docker] is a tool that allows you to build and run containers. +[Podman](https://podman.io/) is a tool that allows you to build and run containers. It's not the only tool that can create containers, but is the one we've chosen for this workshop. ## Container Images @@ -169,7 +169,7 @@ tools into containers? This solves several of our problems: - documentation -- there is a clear record of what software and software dependencies were used, from bottom to top. -- portability -- the container can be used on any computer that has Docker installed -- it doesn't matter whether the computer is Mac, Windows or Linux-based. +- portability -- the container can be used on any computer that has a compliant container runtime such as Podman or Docker installed -- it doesn't matter whether the computer is Mac, Windows or Linux-based. - reproducibility -- you can use the exact same software and environment on your computer and on other resources (like a large-scale computing cluster). - configurability -- containers can be sized to take advantage of more resources (memory, CPU, etc.) on large systems (clusters) or less, depending on the circumstances. @@ -186,8 +186,8 @@ a research context include: - Using containers solely on your own computer to use a specific software tool or to test out a tool (possibly to avoid a difficult and complex installation process, to save your time or to avoid dependency hell). -- Creating a `Dockerfile` that generates a container image with software that you - specify installed, then sharing a container image generated using this Dockerfile with +- Creating a `Dockerfile` or `Containerfile` that generates a container image with software that you + specify installed, then sharing a container image generated using this file with your collaborators for use on their computers or a remote computing resource (e.g. cloud-based or HPC system). - Archiving the container images so you can repeat analysis/modelling using the @@ -206,6 +206,6 @@ a research context include: - Virtualization allows multiple environments to run on a single computer. - Containerization improves upon the virtualization of whole computers by allowing efficient management of the host computer's memory and storage resources. - Containers are built from 'recipes' that define the required set of software components and the instructions necessary to build/install them within a container image. -- Docker is just one software platform that can create containers and the resources they use. +- Podman is just one software platform that can create containers and the resources they use. :::::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/episodes/managing-containers.md b/episodes/managing-containers.md index e1c350e6e..ab5102bfc 100644 --- a/episodes/managing-containers.md +++ b/episodes/managing-containers.md @@ -13,7 +13,7 @@ exercises: 0 :::::::::::::::::::::::::::::::::::::::: questions -- How do I interact with a Docker container on my computer? +- How do I interact with a container on my computer? - How do I manage my containers and container images? :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -26,56 +26,62 @@ In order to remove a specific container image, you need to find out details abou specifically, the "Image ID". For example, say my laptop contained the following container image: ```bash -$ docker image ls +$ podman image ls ``` ```output -REPOSITORY TAG IMAGE ID CREATED SIZE -hello-world latest fce289e99eb9 15 months ago 1.84kB +REPOSITORY TAG IMAGE ID CREATED SIZE +quay.io/podman/hello latest 83fc7ce1224f 14 months ago 580 kB ``` -You can remove the container image with a `docker image rm` command that includes the *Image ID*, such as: +You can remove the container image with a `podman image rm` command that includes the *Image ID*, such as: ```bash -$ docker image rm fce289e99eb9 +$ podman image rm 83fc7ce1224f ``` or use the container image name, like so: ```bash -$ docker image rm hello-world +$ podman image rm quay.io/podman/hello +``` + +You can also drop `quay.io/podman/` and only use the short name `hello` as there is no other image with this name. If you had another image called `hello` from another registry, you would need to specify the full name to distinguish between them. + +```bash +podman image rm hello ``` However, you may see this output: ```output -Error response from daemon: conflict: unable to remove repository reference "hello-world" (must force) - container e7d3b76b00f4 is using its referenced image fce289e99eb9 +Error: image used by 2061ddb499b6e0d856cfd1d2dee2b0a365f577256ff76d6e29615f1701ddb420: image is in use by a container: consider listing external containers and force-removing image ``` -This happens when Docker hasn't cleaned up some of the previously running containers +This happens when Podman hasn't cleaned up some of the previously running containers based on this container image. So, before removing the container image, we need to be able to see what containers are currently running, or have been run recently, and how to remove these. ## What containers are running? -Working with containers, we are going to shift back to the command: `docker container`. Similar to `docker image`, we can list running containers by typing: +Working with containers, we are going to shift back to the command: `podman container`. Similar to `podman image`, we can list running containers by typing: ```bash -$ docker container ls +$ podman container ls ``` ```output -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ``` Notice that this command didn't return any containers because our containers all exited and thus stopped running after they completed their work. ::::::::::::::::::::::::::::::::::::::::: callout -## `docker ps` +## `podman ps` -The command `docker ps` serves the same purpose as `docker container ls`, and comes +The command `podman ps` serves the same purpose as `podman container ls`, and comes from the Unix shell command `ps` which describes running processes. @@ -83,24 +89,24 @@ from the Unix shell command `ps` which describes running processes. ## What containers have run recently? -There is also a way to list running containers, and those that have completed recently, which is to add the `--all`/`-a` flag to the `docker container ls` command as shown below. +There is also a way to list running containers, and those that have completed recently, which is to add the `--all`/`-a` flag to the `podman container ls` command as shown below. ```bash -$ docker container ls --all +$ podman container ls --all ``` ```output -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -9c698655416a hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago zen_dubinsky -6dd822cf6ca9 hello-world "/hello" 3 minutes ago Exited (0) 3 minutes ago eager_engelbart +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +2061ddb499b6 quay.io/podman/hello:latest /usr/local/bin/po... 8 minutes ago Exited (0) 8 minutes ago suspicious_swanson +6091eac31f58 quay.io/podman/hello:latest /usr/local/bin/po... 2 seconds ago Exited (0) 2 seconds ago ecstatic_nash ``` ::::::::::::::::::::::::::::::::::::::::: callout ## Keeping it clean -You might be surprised at the number of containers Docker is still keeping track of. -One way to prevent this from happening is to add the `--rm` flag to `docker container run`. This +You might be surprised at the number of containers Podman is still keeping track of. +One way to prevent this from happening is to add the `--rm` flag to `podman container run`. This will completely wipe out the record of the run container when it exits. If you need a reference to the running container for any reason, **don't** use this flag. @@ -113,14 +119,20 @@ To delete an exited container you can run the following command, inserting the ` It will repeat the `CONTAINER ID` back to you, if successful. ```bash -$ docker container rm 9c698655416a +$ podman container rm 6091eac31f58 ``` ```output -9c698655416a +6091eac31f58 ``` -An alternative option for deleting exited containers is the `docker container prune` command. Note that this command doesn't accept a container ID as an +You can equivalently provide the `NAME` of the container to remove it. + +```bash +$ podman container rm suspicious_swanson +``` + +An alternative option for deleting exited containers is the `podman container prune` command. Note that this command doesn't accept a container ID as an option because it deletes ALL exited containers! **Be careful** with this command as deleting the container is **forever**. **Once a container is deleted you can not get it back.** @@ -130,37 +142,49 @@ If successful it will print the full `CONTAINER ID` back to you for each contain removed. ```bash -$ docker container prune +$ podman container prune ``` ```output -WARNING! This will remove all stopped containers. +WARNING! This will remove all non running containers. Are you sure you want to continue? [y/N] y -Deleted Containers: -9c698655416a848278d16bb1352b97e72b7ea85884bff8f106877afe0210acfc -6dd822cf6ca92f3040eaecbd26ad2af63595f30bb7e7a20eacf4554f6ccc9b2b +400f00fc395f2e995130970dc0efe0b27e9a43a0a2bc9389aad9c62810a6573a +670bfc78bcc54332c1d9de5e09dc3cf4478e12ebb37e9d00d6e228decbb1c25a ``` ## Removing images, for real this time Now that we've removed any potentially running or stopped containers, we can try again to -delete the `hello-world` **container image**. +delete the `hello` **container image**. ```bash -$ docker image rm hello-world +$ podman image rm hello ``` ```output -Untagged: hello-world:latest -Untagged: hello-world@sha256:5f179596a7335398b805f036f7e8561b6f0e32cd30a32f5e19d17a3cda6cc33d -Deleted: sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e -Deleted: sha256:af0b15c8625bb1938f1d7b17081031f649fd14e6b233688eea3c5483994a66a3 +Untagged: quay.io/podman/hello:latest +Deleted: 83fc7ce1224f5ed3885f6aaec0bb001c0bbb2a308e3250d7408804a720c72a32 ``` -The reason that there are a few lines of output, is that a given container image may have been formed by merging multiple underlying layers. -Any layers that are used by multiple Docker container images will only be stored once. -Now the result of `docker image ls` should no longer include the `hello-world` container image. +The image you delete may have been formed by merging multiple underlying layers. +In this case, you may see multiple lines of deletions when running `podman image +rm` on what appears to be a single image. Any layers that are used by multiple +container images will only be stored once. Now the result of `podman image ls` +should no longer include the `hello` container image. + +::::::::::::::::::::::::::::::::::::::::: callout + +## Using the GUI + +If you have installed the Podman Desktop GUI, you should be able to use its +GUI to view and delete containers and container images. It will provide the same +information as the command line `podman` tools, and you will still need to +delete containers before the associated container image. Nevertheless, it's still +worth learning to use `podman` on the terminal as this underpins the rest of the +technology and it's not guaranteed that all systems you work on will have a +GUI to use! +:::::::::::::::::::::::::::::::::::::::::::::::::: - -:::::::::::::::::::::::::::::::::::::::: keypoints - -- A toolbar icon indicates that Docker is ready to use (on Windows and macOS). -- You will typically interact with Docker using the command line. -- To learn how to run a certain Docker command, we can type the command followed by the `--help` flag. - -:::::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/episodes/meet-podman.md b/episodes/meet-podman.md new file mode 100644 index 000000000..cf986ff34 --- /dev/null +++ b/episodes/meet-podman.md @@ -0,0 +1,458 @@ +--- +title: Introducing the Podman Command Line +teaching: 10 +exercises: 5 +--- + +::::::::::::::::::::::::::::::::::::::: objectives + +- Explain how to check that Podman is installed and is ready to use. +- Demonstrate some initial Podman command line interactions. +- Use the built-in help for Podman commands. + +:::::::::::::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::: questions + +- How do I know Podman is installed and running? +- How do I interact with Podman? + +:::::::::::::::::::::::::::::::::::::::::::::::::: + +## Podman command line + +Start the Podman application that you installed in working through the setup instructions for this session. Note that this might not be necessary if your laptop is running Linux or if the installation added the Podman application to your startup process. + +::::::::::::::::::::::::::::::::::::::::: callout + +## You may need to login to Docker Hub + +The Podman Desktop application will usually provide a way for you to log in to +the Docker Hub via the 'Settings' menu followed by 'Registries' and then +'Configure' under the Docker Hub entry. It is usually convenient to do this when +the application starts. This will require you to use your Docker Hub username +and your password. We will not actually require access to the Docker Hub until +later in the course but if you can login now, you should do so. + + +:::::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::: callout + +## Determining your Docker Hub username + +If you no longer recall your Docker Hub username, e.g., because you have been logging into the Docker Hub using your email address, +you can find out what it is through the steps: + +- Open [https://hub.docker.com/](https://hub.docker.com/) in a web browser window +- Sign-in using your email and password (don't tell us what it is) +- In the top-right of the screen you will see your username + + +:::::::::::::::::::::::::::::::::::::::::::::::::: + +Once your Podman application is running, open a shell (terminal) window, and run the following command to check that Podman is installed and the command line tools are working correctly. Below is the output for a Mac version, but the specific version is unlikely to matter much: it does not have to precisely match the one listed below. + +```bash +$ podman --version +``` + +```output +podman version 5.4.2 +``` + +The above command has not actually relied on the part of Podman that runs containers, just that Podman +is installed and you can access it correctly from the command line. + +A command that checks that Podman is working correctly is the `podman container ls` command (we cover this command in more detail later in the course). + +Without explaining the details, output on a newly installed system would likely be: + +```bash +$ podman container ls +``` + +```output +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +``` + +(The command `podman system info` could also be used to verify that Podman is correctly installed and operational but it produces a larger amount of output.) + +However, if you instead get a message similar to the following + +```output +Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VM +Error: unable to connect to Podman socket: failed to connect: dial tcp 127.0.0.1:63249: connect: connection refused +``` + +then you need to check that you have started the Podman Desktop application or Podman Machine or however else you worked through the setup instructions. + +## Getting help + +Often when working with a new command line tool, we need to get help. These tools often have some +sort of subcommand or flag (usually `help`, `-h`, or `--help`) that displays a prompt describing how to use the +tool. For Podman, it's no different. If we run `podman --help`, we see the following output (running `podman` also produces the help message): + +```output +Manage pods, containers and images + +Usage: + podman [options] [command] + +Available Commands: + attach Attach to a running container + build Build an image using instructions from Containerfiles + commit Create new image based on the changed container + compose Run compose workloads via an external provider such as docker-compose or podman-compose + container Manage containers + cp Copy files/folders between a container and the local filesystem + create Create but do not start a container + diff Display the changes to the object's file system + events Show podman system events + exec Run a process in a running container + export Export container's filesystem contents as a tar archive + farm Farm out builds to remote machines + generate Generate structured data based on containers, pods or volumes + healthcheck Manage health checks on containers + help Help about any command + history Show history of a specified image + image Manage images + images List images in local storage + import Import a tarball to create a filesystem image + info Display podman system information + init Initialize one or more containers + inspect Display the configuration of object denoted by ID + kill Kill one or more running containers with a specific signal + kube Play containers, pods or volumes from a structured file + load Load image(s) from a tar archive + login Log in to a container registry + logout Log out of a container registry + logs Fetch the logs of one or more containers + machine Manage a virtual machine + manifest Manipulate manifest lists and image indexes + network Manage networks + pause Pause all the processes in one or more containers + pod Manage pods + port List port mappings or a specific mapping for the container + ps List containers + pull Pull an image from a registry + push Push an image to a specified destination + rename Rename an existing container + restart Restart one or more containers + rm Remove one or more containers + rmi Remove one or more images from local storage + run Run a command in a new container + save Save image(s) to an archive + search Search registry for image + secret Manage secrets + start Start one or more containers + stats Display a live stream of container resource usage statistics + stop Stop one or more containers + system Manage podman + tag Add an additional name to a local image + top Display the running processes of a container + unpause Unpause the processes in one or more containers + untag Remove a name from a local image + update Update an existing container + version Display the Podman version information + volume Manage volumes + wait Block on one or more containers + +Options: + --config string Location of authentication config file + -c, --connection string Connection to use for remote Podman service (CONTAINER_CONNECTION) (default "podman-machine-default-root") + --help Help for podman + --identity string path to SSH identity file, (CONTAINER_SSHKEY) (default "/Users/william/.local/share/containers/podman/machine/machine") + --log-level string Log messages above specified level (trace, debug, info, warn, warning, error, fatal, panic) (default "warn") + --out string Send output (stdout) from podman to a file + --ssh string define the ssh mode (default "golang") + --storage-opt stringArray Used to pass an option to the storage driver + --url string URL to access Podman service (CONTAINER_HOST) (default "ssh://root@127.0.0.1:63249/run/podman/podman.sock") + -v, --version version for podman +``` + +We can view further help on the individual Podman commands by adding `--help` to that command. For example, take the `podman container ls` command that we ran previously. We can see from the Podman help prompt that `container` is a Podman command, so to get help for that command, we run: + +```bash +podman container --help # or instead 'podman container' +``` + +```output +Manage containers + +Description: + Manage containers + +Usage: + podman container [command] + +Available Commands: + attach Attach to a running container + checkpoint Checkpoint one or more containers + clone Clone an existing container + commit Create new image based on the changed container + cp Copy files/folders between a container and the local filesystem + create Create but do not start a container + diff Inspect changes to the container's file systems + exec Run a process in a running container + exists Check if a container exists in local storage + export Export container's filesystem contents as a tar archive + init Initialize one or more containers + inspect Display the configuration of a container + kill Kill one or more running containers with a specific signal + list List containers + logs Fetch the logs of one or more containers + pause Pause all the processes in one or more containers + port List port mappings or a specific mapping for the container + prune Remove all non running containers + ps List containers + rename Rename an existing container + restart Restart one or more containers + restore Restore one or more containers from a checkpoint + rm Remove one or more containers + run Run a command in a new container + start Start one or more containers + stats Display a live stream of container resource usage statistics + stop Stop one or more containers + top Display the running processes of a container + unpause Unpause the processes in one or more containers + update Update an existing container + wait Block on one or more containers +``` + +There's also help for the `container ls` command: + +```bash +podman container ls --help # this one actually requires the '--help' flag +``` + +```output +List containers + +Description: + Prints out information about the containers + +Usage: + podman container list [options] + +Aliases: + list, ls + +Examples: + podman container list -a + podman container list -a --format "{{.ID}} {{.Image}} {{.Labels}} {{.Mounts}}" + podman container list --size --sort names + +Options: + -a, --all Show all the containers, default is only running containers + --external Show containers in storage not controlled by Podman + -f, --filter stringArray Filter output based on conditions given + --format string Pretty-print containers to JSON or using a Go template + -n, --last int Print the n last created containers (all states) (default -1) + --no-trunc Display the extended information + --noheading Do not print headers + --ns Display namespace information + -p, --pod Print the ID and name of the pod the containers are associated with + -q, --quiet Print the numeric IDs of the containers only + -s, --size Display the total file sizes + --sort choice Sort output by: command, created, id, image, names, runningfor, size, status + --sync Sync container state with OCI runtime + -w, --watch uint Watch the ps output on an interval in seconds +``` + +You may notice that there are many commands that stem from the `podman` command. Instead of trying to remember +all possible commands and options, it's better to learn how to effectively get help from the command line. Although +we can always search the web, getting the built-in help from our tool is often much faster and may provide the answer +right away. This applies not only to Podman, but also to most command line-based tools. + + + +::::::::::::::::::::::::::::::::::::::: challenge + +## Exploring a command + +Run `podman --help` and pick a command from the list. +Explore the help prompt for that command. Try to guess how a command would work by looking at the `Usage: ` +section of the prompt. + +::::::::::::::: solution + +## Solution + +Suppose we pick the `podman image build` command: + +```bash +podman image build --help +``` + +```output +Build an image using instructions from Containerfiles + +Description: + Builds an OCI or Docker image using instructions from one or more Containerfiles and a specified build context directory. + +Usage: + podman image build [options] [CONTEXT] + +Examples: + podman image build . + podman image build --creds=username:password -t imageName -f Containerfile.simple . + podman image build --layers --force-rm --tag imageName . + +Options: + --add-host host:ip add a custom host-to-IP mapping (host:ip) (default []) + --all-platforms attempt to build for all base image platforms + --annotation stringArray set metadata for an image (default []) + --arch string set the ARCH of the image to the provided value instead of the architecture of the host (default "arm64") + --authfile string path of the authentication file. + --build-arg argument=value argument=value to supply to the builder + --build-arg-file argfile.conf argfile.conf containing lines of argument=value to supply to the builder + --build-context argument=value argument=value to supply additional build context to the builder + --cache-from stringArray remote repository list to utilise as potential cache source. + --cache-to stringArray remote repository list to utilise as potential cache destination. + --cache-ttl string only consider cache images under specified duration. + --cap-add strings add the specified capability when running (default []) + --cap-drop strings drop the specified capability when running (default []) + --cert-dir string use certificates at the specified path to access the registry + --cgroup-parent string optional parent cgroup for the container + --cgroupns string 'private', or 'host' + --compat-volumes preserve the contents of VOLUMEs during RUN instructions + --cpp-flag stringArray set additional flag to pass to C preprocessor (cpp) + --cpu-period uint limit the CPU CFS (Completely Fair Scheduler) period + --cpu-quota int limit the CPU CFS (Completely Fair Scheduler) quota + -c, --cpu-shares uint CPU shares (relative weight) + --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1) + --cpuset-mems string memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems. + --created-annotation set an "org.opencontainers.image.created" annotation in the image (default true) + --creds [username[:password]] use [username[:password]] for accessing the registry + --decryption-key strings key needed to decrypt the image + --device stringArray additional devices to provide + -D, --disable-compression don't compress layers by default (default true) + --dns /etc/resolv.conf set custom DNS servers or disable it completely by setting it to 'none', which prevents the automatic creation of /etc/resolv.conf. + --dns-option strings set custom DNS options + --dns-search strings set custom DNS search domains + --env stringArray set environment variable for the image + -f, --file pathname or URL pathname or URL of a Dockerfile + --force-rm always remove intermediate containers after a build, even if the build is unsuccessful. (default true) + --format format format of the built image's manifest and metadata. Use BUILDAH_FORMAT environment variable to override. (default "oci") + --from string image name used to replace the value in the first FROM instruction in the Containerfile + --group-add strings add additional groups to the primary container process. 'keep-groups' allows container processes to use supplementary groups. + --hooks-dir stringArray set the OCI hooks directory path (may be set multiple times) + --http-proxy pass through HTTP Proxy environment variables (default true) + --identity-label add default identity label (default true) + --ignorefile string path to an alternate .dockerignore file + --iidfile file file to write the image ID to + --inherit-annotations inherit the annotations from the base image or base stages. (default true) + --inherit-labels inherit the labels from the base image or base stages. (default true) + --ipc path 'private', path of IPC namespace to join, or 'host' + --isolation type type of process isolation to use. Use BUILDAH_ISOLATION environment variable to override. (default "rootless") + --jobs int how many stages to run in parallel (default 1) + --label stringArray set metadata for an image (default []) + --layer-label stringArray set metadata for an intermediate image (default []) + --layers use intermediate layers during build. Use BUILDAH_LAYERS environment variable to override. (default true) + --logfile file log to file instead of stdout/stderr + --manifest string add the image to the specified manifest list. Creates manifest list if it does not exist + -m, --memory string memory limit (format: [], where unit = b, k, m or g) + --memory-swap string swap limit equal to memory plus swap: '-1' to enable unlimited swap + --network string 'private', 'none', 'ns:path' of network namespace to join, or 'host' + --no-cache do not use existing cached images for the container build. Build from the start with a new set of cached layers. + --no-hostname do not create new /etc/hostname file for RUN instructions, use the one from the base image. + --no-hosts do not create new /etc/hosts file for RUN instructions, use the one from the base image. + --omit-history omit build history information from built image + --os string set the OS to the provided value instead of the current operating system of the host (default "darwin") + --os-feature feature set required OS feature for the target image in addition to values from the base image + --os-version version set required OS version for the target image instead of the value from the base image + --pid path private, path of PID namespace to join, or 'host' + --platform OS/ARCH[/VARIANT] set the OS/ARCH[/VARIANT] of the image to the provided value instead of the current operating system and architecture of the host (for example "linux/arm") (default [darwin/arm64/v8]) + --pull string[="always"] Pull image policy ("always"|"missing"|"never"|"newer") (default "missing") + -q, --quiet refrain from announcing build instructions and image read/write progress + --retry int number of times to retry in case of failure when performing push/pull (default 3) + --retry-delay string delay between retries in case of push/pull failures + --rewrite-timestamp set timestamps in layers to no later than the value for --source-date-epoch + --rm remove intermediate containers after a successful build (default true) + --runtime-flag strings add global flags for the container runtime + --sbom preset scan working container using preset configuration + --sbom-image-output path add scan results to image as path + --sbom-image-purl-output path add scan results to image as path + --sbom-merge-strategy strategy merge scan results using strategy + --sbom-output file save scan results to file + --sbom-purl-output file save scan results to file` + --sbom-scanner-command command scan working container using command in scanner image + --sbom-scanner-image image scan working container using scanner command from image + --secret stringArray secret file to expose to the build + --security-opt stringArray security options (default []) + --shm-size size of '/dev/shm'. The format is . (default "65536k") + --skip-unused-stages skips stages in multi-stage builds which do not affect the final target (default true) + --source-date-epoch seconds set new timestamps in image info to seconds after the epoch, defaults to current time + --squash squash all image layers into a single layer + --squash-all Squash all layers into a single layer + --ssh stringArray SSH agent socket or keys to expose to the build. (format: default|[=|[,]]) + --stdin pass stdin into containers + -t, --tag name tagged name to apply to the built image + --target string set the target build stage to build + --timestamp seconds set new timestamps in image info and layer to seconds after the epoch, defaults to current times + --ulimit strings ulimit options + --unsetannotation strings unset annotation when inheriting annotations from base image + --unsetenv strings unset environment variable from final image + --unsetlabel strings unset label when inheriting labels from base image + --userns path 'container', path of user namespace to join, or 'host' + --userns-gid-map containerGID:hostGID:length containerGID:hostGID:length GID mapping to use in user namespace + --userns-gid-map-group name name of entries from /etc/subgid to use to set user namespace GID mapping + --userns-uid-map containerUID:hostUID:length containerUID:hostUID:length UID mapping to use in user namespace + --userns-uid-map-user name name of entries from /etc/subuid to use to set user namespace UID mapping + --uts path private, :path of UTS namespace to join, or 'host' + --variant variant override the variant of the specified image + -v, --volume stringArray bind mount a volume into the container +``` + +We could try to guess that the command could be run like this: + +```bash +podman image build . +``` + +or + +```bash +podman image build https://github.com/docker/rootfs.git +``` + +where `https://github.com/docker/rootfs.git` could be any relevant URL that supports a Docker-style image. + + + +::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::::: + + + + + +:::::::::::::::::::::::::::::::::::::::: keypoints + +- You will typically interact with Podman using the command line. +- To learn how to run a certain Podman command, we can type the command followed by the `--help` flag. + +:::::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/episodes/reproduciblity.md b/episodes/reproduciblity.md index 8a4a90afe..7be9541d3 100644 --- a/episodes/reproduciblity.md +++ b/episodes/reproduciblity.md @@ -19,7 +19,7 @@ exercises: 5 :::::::::::::::::::::::::::::::::::::::::::::::::: Although this workshop is titled "Reproducible computational environments using containers", -so far we have mostly covered the mechanics of using Docker with only passing reference to +so far we have mostly covered the mechanics of using Podman with only passing reference to the reproducibility aspects. In this section, we discuss these aspects in more detail. ::::::::::::::::::::::::::::::::::::::::: callout @@ -71,10 +71,10 @@ This is fine for working collaboratively with container images on a day-to-day b When you publish your work or make it publicly available in some way it is good practice to make container images that you used for computational work available in an immutable, persistent way and to have an identifier that allows people to cite and give you credit for the work you have done. [Zenodo](https://zenodo.org/) is one service that provides this functionality. -Zenodo supports the upload of *tar* archives and we can capture our Docker container images as tar archives using the `docker image save` command. For example, to export the container image we created earlier in this lesson: +Zenodo supports the upload of *tar* archives and we can capture our container images as tar archives using the `podman image save` command. For example, to export the container image we created earlier in this lesson: ```bash -docker image save alice/alpine-python:v1 -o alpine-python.tar +podman image save docker.io/alice/alpine-python:v1 -o alpine-python.tar ``` These tar container images can become quite large and Zenodo supports uploads up to 50GB so you may need to compress your archive to make it fit on Zenodo using a tool such as gzip (or zip): @@ -85,7 +85,7 @@ gzip alpine-python.tar Once you have your archive, you can [deposit it on Zenodo](https://zenodo.org/deposit/) and this will: -- Create a long-term archive snapshot of your Docker container image which people (including your future self) can download and reuse or reproduce your work. +- Create a long-term archive snapshot of your container image which people (including your future self) can download and reuse or reproduce your work. - Create a persistent DOI (*Digital Object Identifier*) that you can cite in any publications or outputs to enable reproducibility and recognition of your work. In addition to the archive file itself, the deposit process will ask you to provide some basic metadata to classify the container image and the associated work. @@ -149,7 +149,7 @@ This is not an exhaustive list but some of the advantages and disadvantages coul - Potentially easier to maintain (though could be opposite if working with large, distributed group) - Disadvantages: - Could get very large in size, making it more difficult to distribute - - Could use [Docker multi-stage build](https://docs.docker.com/develop/develop-images/multistage-build) to reduce size + - Could use [multi-stage build](https://docs.docker.com/build/building/multi-stage/) (described here for Docker but works equivalently with Podman) to reduce size - May end up with same dependency issues within the container image from different software requirements - Potentially more complex to test - Less re-useable for different, but related, work @@ -179,7 +179,7 @@ This is not an exhaustive list but some of the advantages and disadvantages coul Now that we're at the end of the lesson material, take a moment to reflect on what you've learned, how it applies to you, and what to do next. -1. In your own notes, write down or diagram your understanding of Docker containers and container images: +1. In your own notes, write down or diagram your understanding of containers and container images: concepts, commands, and how they work. 2. In the workshop's shared notes document, write down how you think you might use containers in your daily work. If there's something you want to try doing with diff --git a/episodes/running-containers.md b/episodes/running-containers.md index 4db2d815e..c7c26bc6e 100644 --- a/episodes/running-containers.md +++ b/episodes/running-containers.md @@ -6,16 +6,16 @@ exercises: 10 ::::::::::::::::::::::::::::::::::::::: objectives -- Use the correct command to see which Docker container images are on your computer. -- Be able to download new Docker container images. +- Use the correct command to see which container images are on your computer. +- Be able to download new container images. - Demonstrate how to start an instance of a container from a container image. -- Describe at least two ways to execute commands inside a running Docker container. +- Describe at least two ways to execute commands inside a running container. :::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::::::::: questions -- How do I interact with Docker containers and container images on my computer? +- How do I interact with Podman containers and container images on my computer? :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -28,45 +28,50 @@ Recall that a *container image* is the template from which particular instances :::::::::::::::::::::::::::::::::::::::::::::::::: -Let's explore our first Docker container. The Docker team provides a simple container -image online called `hello-world`. We'll start with that one. +Let's explore our first Podman container. The Podman team provides a simple container +image online called `hello`. We'll start with that one. -## Downloading Docker images +## Downloading Podman images -The `docker image` command is used to interact with Docker container images. +The `podman image` command is used to interact with Podman container images. You can find out what container images you have on your computer by using the following command ("ls" is short for "list"): ```bash -$ docker image ls +$ podman image ls ``` -If you've just -installed Docker, you won't see any container images listed. +If you've just installed Podman, you won't see any container images listed. -To get a copy of the `hello-world` Docker container image from the internet, run this command: +To get a copy of the `hello` Podman container image from the internet, run this command: ```bash -$ docker image pull hello-world +$ podman image pull hello ``` You should see output like this: ```output -Using default tag: latest -latest: Pulling from library/hello-world -1b930d010525: Pull complete -Digest: sha256:f9dfddf63636d84ef479d645ab5885156ae030f611a56f3a7ac7f2fdd86d7e4e -Status: Downloaded newer image for hello-world:latest -docker.io/library/hello-world:latest +Resolved "hello" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf) +Trying to pull quay.io/podman/hello:latest... +Getting image source signatures +Copying blob sha256:1ff9adeff4443b503b304e7aa4c37bb90762947125f4a522b370162a7492ff47 +Copying config sha256:83fc7ce1224f5ed3885f6aaec0bb001c0bbb2a308e3250d7408804a720c72a32 +Writing manifest to image destination +83fc7ce1224f5ed3885f6aaec0bb001c0bbb2a308e3250d7408804a720c72a32 ``` ::::::::::::::::::::::::::::::::::::::::: callout ## Docker Hub -Where did the `hello-world` container image come from? It came from the Docker Hub -website, which is a place to share Docker container images with other people. More on that -in a later episode. +Where did the `hello` container image come from? If you look carefully in the +output when you pulled the image, you will see that it came from the Quay container +registry, which is a place to share container images with other people. Specifically, +Podman expanded the short container name to `quay.io/podman/hello`. +Other container registries exist, sometimes with differing use cases. Docker Hub is probably the +most widely used. Although under the 'Docker' name, Docker Hub can be used by any +compatible containerization service, including Podman and Singularity. We can get Docker's +version of a `hello` image by instead pulling `docker.io/hello-world`. :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -75,7 +80,7 @@ in a later episode. ## Exercise: Check on Your Images -What command would you use to see if the `hello-world` Docker container image had downloaded +What command would you use to see if the `hello` container image had downloaded successfully and was on your computer? Give it a try before checking the solution. @@ -83,68 +88,67 @@ Give it a try before checking the solution. ## Solution -To see if the `hello-world` container image is now on your computer, run: +To see if the `hello` container image is now on your computer, run: ```bash -$ docker image ls +$ podman image ls ``` ::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::::::::::::::::::: -Note that the downloaded `hello-world` container image is not in the folder where you are in the terminal! (Run +Note that the downloaded `hello` container image is not in the folder where you are in the terminal! (Run `ls` by itself to check.) The container image is not a file like our normal programs and documents; -Docker stores it in a specific location that isn't commonly accessed, so it's necessary -to use the special `docker image` command to see what Docker container images you have on your +Podman stores it in a specific location that isn't commonly accessed, so it's necessary +to use the special `podman image` command to see what Podman container images you have on your computer. -## Running the `hello-world` container +## Running the `hello` container -To create and run containers from named Docker container images you use the `docker container run` command. Try the following `docker container run` invocation. Note that it does not matter what your current working directory is. +To create and run containers from named Podman container images you use the `podman container run` command. Try the following `podman container run` invocation. Note that it does not matter what your current working directory is. ```bash -$ docker container run hello-world +$ podman container run hello ``` ```output -Hello from Docker! -This message shows that your installation appears to be working correctly. - -To generate this message, Docker took the following steps: - 1. The Docker client contacted the Docker daemon. - 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. - (amd64) - 3. The Docker daemon created a new container from that image which runs the - executable that produces the output you are currently reading. - 4. The Docker daemon streamed that output to the Docker client, which sent it - to your terminal. - -To try something more ambitious, you can run an Ubuntu container with: - $ docker run -it ubuntu bash - -Share images, automate workflows, and more with a free Docker ID: - https://hub.docker.com/ - -For more examples and ideas, visit: - https://docs.docker.com/get-started/ +!... Hello Podman World ...! + + .--"--. + / - - \ + / (O) (O) \ + ~~~| -=(,Y,)=- | + .---. /` \ |~~ + ~/ o o \~~~~.----. ~~ + | =(X)= |~ / (O (O) \ + ~~~~~~~ ~| =(Y_)=- | + ~~~~ ~~~| U |~~ + +Project: https://github.com/containers/podman +Website: https://podman.io +Desktop: https://podman-desktop.io +Documents: https://docs.podman.io +YouTube: https://youtube.com/@Podman +X/Twitter: @Podman_io +Mastodon: @Podman_io@fosstodon.org ``` -What just happened? When we use the `docker container run` command, Docker does three things: +What just happened? When we use the `podman container run` command, Podman does three things: | 1\. Starts a Running Container | 2\. Performs Default Action | 3\. Shuts Down the Container | | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | | Starts a running container, based on the container image. Think of this as the "alive" or "inflated" version of the container -- it's actually doing something. | If the container has a default action set, it will perform that default action. This could be as simple as printing a message (as above) or running a whole analysis pipeline! | Once the default action is complete, the container stops running (or exits). The container image is still there, but nothing is actively running. | -The `hello-world` container is set up to run an action by default -- +The `hello` container is set up to run an action by default -- namely to print this message. ::::::::::::::::::::::::::::::::::::::::: callout -## Using `docker container run` to get the image +## Using `podman container run` to get the image -We could have skipped the `docker image pull` step; if you use the `docker container run` -command and you don't already have a copy of the Docker container image, Docker will +We could have skipped the `podman image pull` step; if you use the `podman container run` +command and you don't already have a copy of the Podman container image, Podman will automatically pull the container image first and then run it. @@ -152,15 +156,16 @@ automatically pull the container image first and then run it. ## Running a container with a chosen command -But what if we wanted to do something different with the container? The output -just gave us a suggestion of what to do -- let's use a different Docker container image -to explore what else we can do with the `docker container run` command. The suggestion above -is to use `ubuntu`, but we're going to run a different type of Linux, `alpine` -instead because it's quicker to download. +But what if we wanted to do something different with the container? Let's use a +different container image to explore what else we can do with the `podman +container run` command. One image we could use is `ubuntu` which provides, as +the name suggests, a container running Ubuntu Linux. However, we're going to run +a different type of Linux instead, `alpine`, because it's smaller and so the +image is quicker to download. ::::::::::::::::::::::::::::::::::::::: challenge -## Run the Alpine Docker container +## Run the Alpine Podman container Try downloading the `alpine` container image and using it to run a container. You can do it in two steps, or one. What are they? @@ -168,20 +173,20 @@ two steps, or one. What are they? :::::::::::::::::::::::::::::::::::::::::::::::::: -What happened when you ran the Alpine Docker container? +What happened when you ran the Alpine Podman container? ```bash -$ docker container run alpine +$ podman container run alpine ``` -If you have never used the `alpine` Docker container image on your computer, Docker probably printed a +If you have never used the `alpine` container image on your computer, Podman probably printed a message that it couldn't find the container image and had to download it. If you used the `alpine` container image before, the command will probably show no output. That's because this particular container is designed for you to provide commands yourself. Try running this instead: ```bash -$ docker container run alpine cat /etc/os-release +$ podman container run alpine cat /etc/os-release ``` You should see the output of the `cat /etc/os-release` command, which prints out @@ -202,28 +207,28 @@ Give it a try before checking the solution. Use the same command as above, but with the `echo` command to print a message. ```bash -$ docker container run alpine echo 'Hello World' +$ podman container run alpine echo 'Hello World' ``` ::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::::::::::::::::::: -So here, we see another option -- we can provide commands at the end of the `docker container run` +So here, we see another option -- we can provide commands at the end of the `podman container run` command and they will execute inside the running container. ## Running containers interactively -In all the examples above, Docker has started the container, run a command, and then +In all the examples above, Podman has started the container, run a command, and then immediately stopped the container. But what if we wanted to keep the container running so we could log into it and test drive more commands? The way to do this is by adding the interactive flags `-i` and `-t` (usually combined as `-it`) -to the `docker container run` command and provide a shell (`bash`,`sh`, etc.) -as our command. The `alpine` Docker container image doesn't include `bash` so we need +to the `podman container run` command and provide a shell (`bash`,`sh`, etc.) +as our command. The `alpine` container image doesn't include `bash` so we need to use `sh`. ```bash -$ docker container run -it alpine sh +$ podman container run -it alpine sh ``` ::::::::::::::::::::::::::::::::::::::::: callout @@ -274,17 +279,17 @@ to almost any command will give you more information.) ## Solution 1 -- Interactive -Run an interactive ubuntu container -- you can use `docker image pull` first, or just +Run an interactive ubuntu container -- you can use `podman image pull` first, or just run it with this command: ```bash -$ docker container run -it ubuntu sh +$ podman container run -it ubuntu sh ``` OR you can get the bash shell instead ```bash -$ docker container run -it ubuntu bash +$ podman container run -it ubuntu bash ``` Then try, running these commands @@ -309,13 +314,13 @@ Exit when you're done. Run a ubuntu container, first with a command to read out the Linux version: ```bash -$ docker container run ubuntu cat /etc/os-release +$ podman container run ubuntu cat /etc/os-release ``` Then run a container with a command to print out the apt-get help: ```bash -$ docker container run ubuntu apt-get --help +$ podman container run ubuntu apt-get --help ``` ::::::::::::::::::::::::: @@ -326,17 +331,17 @@ $ docker container run ubuntu apt-get --help ## Even More Options -There are many more options, besides `-it` that can be used with the `docker container run` +There are many more options, besides `-it` that can be used with the `podman container run` command! A few of them will be covered in [later episodes](/advanced-containers) and we'll share two more common ones here: - `--rm`: this option guarantees that any running container is completely removed from your computer after the container is stopped. Without this option, - Docker actually keeps the "stopped" container around, which you'll see in a later + Podman actually keeps the "stopped" container around, which you'll see in a later episode. Note that this option doesn't impact the *container images* that you've pulled, just running instances of containers. -- `--name=`: By default, Docker assigns a random name and ID number to each container +- `--name=`: By default, Podman assigns a random name and ID number to each container instance that you run on your computer. If you want to be able to more easily refer to a specific running container, you can assign it a name using this option. @@ -344,9 +349,9 @@ and we'll share two more common ones here: ## Conclusion -So far, we've seen how to download Docker container images, use them to run commands inside +So far, we've seen how to download container images, use Podman to run commands inside running containers, and even how to explore a running container from the inside. -Next, we'll take a closer look at all the different kinds of Docker container images that are out there. +Next, we'll take a closer look at all the different kinds of container images that are out there. @@ -358,9 +363,9 @@ Next, we'll take a closer look at all the different kinds of Docker container im :::::::::::::::::::::::::::::::::::::::: keypoints -- The `docker image pull` command downloads Docker container images from the internet. -- The `docker image ls` command lists Docker container images that are (now) on your computer. -- The `docker container run` command creates running containers from container images and can run commands inside them. -- When using the `docker container run` command, a container can run a default action (if it has one), a user specified action, or a shell to be used interactively. +- The `podman image pull` command downloads container images from the internet. +- The `podman image ls` command lists Podman container images that are (now) on your computer. +- The `podman container run` command creates running containers from container images and can run commands inside them. +- When using the `podman container run` command, a container can run a default action (if it has one), a user specified action, or a shell to be used interactively. :::::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/index.md b/index.md index b11b92eb3..000d8fc90 100644 --- a/index.md +++ b/index.md @@ -3,20 +3,20 @@ permalink: index.html site: sandpaper::sandpaper_site --- -This session aims to introduce the use of Docker containers with the goal of using them to effect reproducible computational environments. Such environments are useful for ensuring reproducible research outputs, for example. +This session aims to introduce the use of Podman containers with the goal of using them to effect reproducible computational environments. Such environments are useful for ensuring reproducible research outputs, for example. :::::::::::::::::::::::::::::::::::::: objectives ## After completing this session you should: -- Have an understanding of what Docker containers are, why they are useful +- Have an understanding of what Podman containers are, why they are useful and the common terminology used -- Have a working Docker installation on your local system to allow you to +- Have a working Podman installation on your local system to allow you to use containers -- Understand how to use existing Docker containers for common tasks -- Be able to build your own Docker containers by understanding both the role - of a `Dockerfile` in building containers, and the syntax used in `Dockerfile`s -- Understand how to manage Docker containers on your local system +- Understand how to use existing Podman containers for common tasks +- Be able to build your own Podman containers by understanding both the role + of a `Dockerfile`/`Containerfile` in building containers, and the syntax used in `Dockerfile`s +- Understand how to manage Podman containers on your local system - Appreciate issues around reproducibility in software, understand how containers can address some of these issues and what the limits to reproducibility using containers are @@ -24,14 +24,15 @@ This session aims to introduce the use of Docker containers with the goal of usi :::::::::::::::::::::::::::::::::::::::::::::::::: -The practical work in this lesson is primarily aimed at using Docker on your own laptop. Beyond your laptop, software container technologies such as Docker can also be used in the cloud and on high performance computing (HPC) systems. Some of the material in this lesson will be applicable to those environments too. +The practical work in this lesson is primarily aimed at using Podman on your own laptop. Beyond your laptop, software container technologies such as Podman can also be used in the cloud and on high performance computing (HPC) systems. Some of the material in this lesson will be applicable to those environments too. ::::::::::::::::::::::::::::::::::::::::: callout ## Containers on HPC systems -On HPC systems it is more likely that *Singularity* rather than Docker will be the available container technology. -If you are looking for a lesson on using Singularity containers (instead of Docker), see this lesson: +On HPC systems it is more likely that *Singularity* rather than Podman will be the available container technology, +though Podman is becoming more common alongside Singularity. +If you are looking for a lesson on using Singularity containers (instead of Podman), see this lesson: - [Reproducible Computational Environments Using Containers: Introduction to Singularity](https://carpentries-incubator.github.io/singularity-introduction/) @@ -54,7 +55,7 @@ If you are looking for a lesson on using Singularity containers (instead of Dock ## Target audience -This lesson on the use of Docker is intended to be relevant to a wide range of +This lesson on the use of Podman is intended to be relevant to a wide range of researchers, as well as existing and prospective technical professionals. It is intended as a beginner level course that is suitable for people who have no experience of containers. @@ -70,9 +71,9 @@ the [Learner Profiles](/profiles.html) page. ::::::::::::::::::::::::::::::::::::::::: callout -## A note about Docker +## A note about Podman -Docker is a mature, robust and very widely used application. Nonetheless, +Podman is a mature, robust and very widely used application. Nonetheless, it is still under extensive development. New versions are released regularly often containing a range of updates and new features. diff --git a/learners/setup.md b/learners/setup.md index 18fa2c3dc..6dd0c6a64 100644 --- a/learners/setup.md +++ b/learners/setup.md @@ -10,28 +10,29 @@ Please seek help at the start of the lesson if you have not been able to establi ### Files to download -Download the [`docker-intro.zip`](files/docker-intro.zip) file. *This file can alternatively be downloaded from the `files` directory in the [docker-introduction GitHub repository](https://github.com/carpentries-incubator/docker-introduction/blob/gh-pages/files/docker-intro.zip)*. +Download the [`podman-intro.zip`](files/podman-intro.zip) file. *This file can alternatively be downloaded from the `files` directory in the [docker-introduction GitHub repository](https://github.com/carpentries-incubator/docker-introduction/blob/gh-pages/files/podman-intro.zip)*. -Move the downloaded file to your Desktop and unzip it. It should unzip to a folder called `docker-intro`. +Move the downloaded file to your Desktop and unzip it. It should unzip to a folder called `podman-intro`. ### Software to install -Docker's installation experience has steadily improved, however situations will arise in which installing Docker on your computer may not be straightforward unless you have a large amount of technical experience. +Podman's installation experience has steadily improved, however situations will arise in which installing Podman on your computer may not be straightforward unless you have a large amount of technical experience. Workshops try to have helpers on hand that have worked their way through the install process, but do be prepared for some troubleshooting. -In most cases, you will need to have administrator rights on the computer in order to install the Docker software. If you are using a computer managed by your organisation and do not have administrator rights, you *may* be able to get your organisation's IT staff to install Docker for you. Alternatively your IT support staff *may* be able to give you remote access to a server that can run Docker commands. +In most cases, you will need to have administrator rights on the computer in order to install the Podman software. If you are using a computer managed by your organisation and do not have administrator rights, you *may* be able to get your organisation's IT staff to install Podman for you. Alternatively your IT support staff *may* be able to give you remote access to a server that can run Podman commands. -Please try to install the appropriate software from the list below depending on the operating system that your computer is running. Do let the workshop organisers know as early as possible if you are unable to install Docker using these instructions, as there may be other options available. +Please try to install the appropriate software from the list below depending on the operating system that your computer is running. Do let the workshop organisers know as early as possible if you are unable to install Podman using these instructions, as there may be other options available. #### Microsoft Windows -**You must have admin rights to run Docker!** Some parts of the lesson will work without running as admin but if you are unable to `Run as administrator` on your machine some elements of this workshop might not work as described. +**You must have admin rights to run Podman!** Some parts of the lesson will work without running as admin but if you are unable to `Run as administrator` on your machine some elements of this workshop might not work as described. -Ideally, you will be able to install the Docker Desktop software, following the [Docker website's documentation](https://docs.docker.com/docker-for-windows/install/). Note that the instructions for installing Docker Desktop on Windows 10 Home Edition are different from other versions of Windows 10. +Ideally, you will be able to install the Podman Desktop, following the [Podman website's documentation](https://podman-desktop.io/docs/installation/windows-install). +Note that Podman for Windows relies upon installing the Windows Subsystem for Linux (WSL). -Note that the above installation instructions highlight a minimum version or "build" that is required to be able to install Docker on your Windows 10 system. See [Which version of Windows operating system am I running?](https://support.microsoft.com/en-us/windows/which-version-of-windows-operating-system-am-i-running-628bec99-476a-2c13-5296-9dd081cdd808) for details of how to find out which version/build of Windows 10 you have. +Note that the above installation instructions highlight a minimum version or "build" that is required to be able to install Podman on your Windows 10 system. See [Which version of Windows operating system am I running?](https://support.microsoft.com/en-us/windows/which-version-of-windows-operating-system-am-i-running-628bec99-476a-2c13-5296-9dd081cdd808) for details of how to find out which version/build of Windows 10 you have. -If you are unable to follow the above instructions to install Docker Desktop on your Windows system, the final release of the deprecated Docker Toolbox version of Docker for Windows can be downloaded from the [releases page of the Docker Toolbox GitHub repository](https://github.com/docker/toolbox/releases). (Download the `.exe` file for the Windows installer). *Please note that this final release of Docker Toolbox includes an old version of Docker and you are strongly advised not to attempt to use this for any production use. It will, however, enable you to follow along with the lesson material.* +If you are unable to follow the above instructions to install Podman on your Windows system, the final release of the deprecated Docker Toolbox version of Docker for Windows can be downloaded from the [releases page of the Docker Toolbox GitHub repository](https://github.com/docker/toolbox/releases). (Download the `.exe` file for the Windows installer). *Please note that this final release of Docker Toolbox includes an old version of Docker and you are strongly advised not to attempt to use this for any production use. It will, however, enable you to follow along with the lesson material.* ::::::::::::::::::::::::::::::::::::::::: callout @@ -62,68 +63,35 @@ This should suppress the path translation functionality in Git Bash. #### Apple macOS -Ideally, you will be able to install the Docker Desktop software, following the -[Docker website's documentation](https://docs.docker.com/docker-for-mac/install/). -The current version of the Docker Desktop software requires macOS version 10.14 (Mojave) or later. +Ideally, you will be able to install the Podman software, from the +[Podman Github Releases website](https://github.com/containers/podman/releases/). +The current version of the Podman software appears to require macOS version 13 (Ventura) or later, but we have not tested this. If you already use Homebrew or MacPorts to manage your software, and would prefer to use those -tools rather than Docker's installer, you can do so. For Homebrew, you can run the command -`brew install --cask docker`. Note that you still need to run the Docker graphical user interface -once to complete the initial setup, after which time the command line functionality of Docker will -become available. The Homebrew install of Docker also requires a minimum macOS version of 10.14. -The MacPorts Docker port should support older, as well as the most recent, operating system -versions (see the [port details](https://ports.macports.org/port/docker/details/)), but note that -we have not recently tested the Docker installation process via MacPorts. +tools rather than Podman's installer, you can do so. For Homebrew, you can run the command +`brew install podman`. #### Linux -There are too many varieties of Linux to give precise instructions here, but hopefully you can locate documentation for getting Docker installed on your Linux distribution. It may already be installed. If it is not already installed on your system, the [Install Docker Engine](https://docs.docker.com/engine/install/) page provides an overview of supported Linux distributions and pointers to relevant installation information. Alternatively, see: - -- [Docker Engine on CentOS](https://docs.docker.com/install/linux/docker-ce/centos/) -- [Docker Engine on Debian](https://docs.docker.com/install/linux/docker-ce/debian/) -- [Docker Engine on Fedora](https://docs.docker.com/install/linux/docker-ce/fedora/) -- [Docker Engine on Ubuntu](https://docs.docker.com/install/linux/docker-ce/ubuntu/) +If it is not already installed on your system, the [Podman Installation instructions](https://podman.io/docs/installation#linux-distributions) page provides an overview of supported Linux distributions and pointers to relevant installation information. ### Verify Installation To quickly check if the Docker and client and server are working run the following command in a new terminal or ssh session: ```bash -$ docker version +$ podman version ``` ```output -Client: - Version: 20.10.2 - API version: 1.41 - Go version: go1.13.8 - Git commit: 20.10.2-0ubuntu2 - Built: Tue Mar 2 05:52:27 2021 - OS/Arch: linux/arm64 - Context: default - Experimental: true - -Server: - Engine: - Version: 20.10.2 - API version: 1.41 (minimum version 1.12) - Go version: go1.13.8 - Git commit: 20.10.2-0ubuntu2 - Built: Tue Mar 2 05:45:16 2021 - OS/Arch: linux/arm64 - Experimental: false - containerd: - Version: 1.4.4-0ubuntu1 - GitCommit: - runc: - Version: 1.0.0~rc95-0ubuntu1~21.04.1 - GitCommit: - docker-init: - Version: 0.19.0 - GitCommit: +Version: 3.4.4 +API Version: 3.4.4 +Go Version: go1.18.1 +Built: Thu Jan 1 01:00:00 1970 +OS/Arch: linux/amd64 ``` -The above output shows a successful installation and will vary based on your system. The important part is that the "Client" and the "Server" parts are both working and returns information. It is beyond the scope of this document to debug installation problems but common errors include the user not belonging to the `docker` group and forgetting to start a new terminal or ssh session. +The above output shows a successful installation and will vary based on your system. ### A quick tutorial on copy/pasting file contents from episodes of the lesson @@ -150,7 +118,3 @@ Let's say you want to copy text off the lesson website and paste it into a file '@ | Set-Content myfile -encoding ascii ``` - - -