summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcontrib/cirrus/runner.sh7
-rw-r--r--docs/source/Tutorials.rst2
-rw-r--r--docs/source/includes.rst2
-rw-r--r--docs/tutorials/README.md6
-rw-r--r--docs/tutorials/podman-go-bindings.md543
-rw-r--r--libpod/networking_linux.go102
-rw-r--r--pkg/bindings/README.md77
7 files changed, 163 insertions, 576 deletions
diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh
index cac679466..da43ffb0a 100755
--- a/contrib/cirrus/runner.sh
+++ b/contrib/cirrus/runner.sh
@@ -173,7 +173,7 @@ function _run_swagger() {
trap "rm -f $envvarsfile" EXIT # contains secrets
# Warning: These values must _not_ be quoted, podman will not remove them.
#shellcheck disable=SC2154
- cat <<eof>>$envvarsfile
+ cat <<eof >>$envvarsfile
GCPJSON=$GCPJSON
GCPNAME=$GCPNAME
GCPPROJECT=$GCPPROJECT
@@ -336,6 +336,11 @@ msg "************************************************************"
# shellcheck disable=SC2154
if [[ "$PRIV_NAME" == "rootless" ]] && [[ "$UID" -eq 0 ]]; then
+ # Remove /var/lib/cni, it is not required for rootless cni.
+ # We have to test that it works without this directory.
+ # https://github.com/containers/podman/issues/10857
+ rm -rf /var/lib/cni
+
req_env_vars ROOTLESS_USER
msg "Re-executing runner through ssh as user '$ROOTLESS_USER'"
msg "************************************************************"
diff --git a/docs/source/Tutorials.rst b/docs/source/Tutorials.rst
index e48d1e853..cb9ab644d 100644
--- a/docs/source/Tutorials.rst
+++ b/docs/source/Tutorials.rst
@@ -10,5 +10,5 @@ Here are a number of useful tutorials to get you up and running with Podman. If
* `How to sign and distribute container images using Podman <https://github.com/containers/podman/blob/master/docs/tutorials/image_signing.md>`_: Learn how to setup and use image signing with Podman.
* `Podman remote-client tutorial <https://github.com/containers/podman/blob/master/docs/tutorials/remote_client.md>`_: A brief how-to on using the Podman remote-client.
* `How to use libpod for custom/derivative projects <https://github.com/containers/podman/blob/master/docs/tutorials/podman-derivative-api.md>`_: How the libpod API can be used within your own project.
-* `How to use Podman's Go bindings <https://github.com/containers/podman/blob/master/docs/tutorials/podman-go-bindings.md>`_: A brief how-to on using Podman's Go bindings in external applications.
+* `How to use Podman's Go RESTful bindings <https://github.com/containers/podman/tree/main/pkg/bindings>`_: An introduction to using our RESTful Golang bindings in an external application.
* `Common network setups <https://github.com/containers/podman/blob/master/docs/tutorials/basic_networking.md>`_: A basic guide to common network setups for Podman.
diff --git a/docs/source/includes.rst b/docs/source/includes.rst
index 8d3b6e2db..6e04d77f4 100644
--- a/docs/source/includes.rst
+++ b/docs/source/includes.rst
@@ -16,4 +16,4 @@
.. _podman run: http://docs.podman.io/en/latest/markdown/podman-run.1.html
.. _podman build: http://docs.podman.io/en/latest/markdown/podman-build.1.html
.. _podman push: http://docs.podman.io/en/latest/markdown/podman-push.1.html
-.. image:: https://github.com/containers/podman/blob/master/logo/podman-logo.png?raw=true
+.. image:: https://github.com/containers/podman/blob/main/logo/podman-logo.png?raw=true
diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md
index 455459062..2a3c85c55 100644
--- a/docs/tutorials/README.md
+++ b/docs/tutorials/README.md
@@ -28,10 +28,6 @@ How the libpod API can be used within your own project.
Learn how to setup and use image signing with Podman.
-**[Go Bindings](podman-go-bindings.md)**
-
-A brief how-to on using Podman's Go bindings in external applications.
-
-**[Go Bindings](basic_networking.md)**
+**[Basic Networking](basic_networking.md)**
A basic guide to common network setups with Podman
diff --git a/docs/tutorials/podman-go-bindings.md b/docs/tutorials/podman-go-bindings.md
deleted file mode 100644
index 2bbf4e5de..000000000
--- a/docs/tutorials/podman-go-bindings.md
+++ /dev/null
@@ -1,543 +0,0 @@
-![PODMAN logo](../../logo/podman-logo-source.svg)
-
-# Podman Go bindings
-
-## Introduction
-
-In the release of Podman 2.0, we removed the experimental tag
-from its recently introduced RESTful service. While it might
-be interesting to interact with a RESTFul server using curl,
-using a set of Go based bindings is probably a more direct
-route to a production ready application. Let’s take a look
-at how easily that can be accomplished.
-
-If you haven't yet, [install Go](https://golang.org/doc/install).
-
-Be careful to double-check that the version of golang is new
-enough (i.e. `go version`), version 1.13.x or higher is
-supported. If needed, Go sources and binaries can be fetched
-from the [official Go website](https://golang.org/dl/).
-
-The Podman Go bindings are a set of functions to allow
-developers to execute Podman operations from within their Go
-based application. The Go bindings connect to a Podman service
-which can run locally or on a remote machine. You can perform
-many operations including pulling and listing images, starting,
-stopping or inspecting containers. Currently, the Podman
-repository has bindings available for operations on images,
-containers, pods, networks and manifests among others. The
-bindings are available on the [v2.0 branch in the
-upstream Podman repository](https://github.com/containers/podman/tree/v2.0).
-You can fetch the bindings for your application using Go modules:
-
-```bash
-$ cd $HOME
-$ mkdir example && cd example
-$ go mod init example.com
-go: creating new go.mod: module example.com
-$ go get github.com/containers/podman/v3
-[...]
-```
-
-This creates a new `go.mod` file in the current directory that looks as follows:
-
-```bash
-module example.com
-
-go 1.16
-
-require github.com/containers/libpod/v3 v3.0.1 // indirect
-```
-
-You can also try a demo application with the Go modules created already:
-
-```bash
-$ git clone https://github.com/containers/Demos
-$ cd Demos/podman_go_bindings
-$ ls
-README.md go.mod go.sum main.go
-```
-
-
-## How do I use them
-
-In this tutorial, you will learn through basic examples how to:
-
-0. [Start the Podman system service](#start-service)
-1. [Connect to the Podman system service](#connect-service)
-2. [Pull images](#pull-images)
-3. [List images](#list-images)
-4. [Create and start a container from an image](#create-start-container)
-5. [List containers](#list-containers)
-6. [Inspect the container](#inspect-container)
-7. [Stop the container](#stop-container)
-8. [Debugging tips](#debugging-tips)
-
-
-### Start the Podman system service <a name="start-service"></a>
-The recommended way to start Podman system service in production mode
-is via systemd socket-activation:
-
-```bash
-$ systemctl --user start podman.socket
-```
-
-There’s no timeout specified when starting the system service via socket-activation.
-
-For purposes of this demo, we will start the service using the Podman
-command itself. If you prefer the system service to timeout after, say,
-5000 seconds, you can run it like so:
-
-```bash
-$ podman system service -t 5000
-```
-
-Note that the 5000 seconds uptime is refreshed after every command is received.
-If you want the service to stay up until the machine is shutdown or the process
-is terminated, use `0` (zero) instead of 5000. For this demo, we will use no timeout:
-
-```bash
-$ podman system service -t 0
-```
-
-
-Open another terminal window and check if the Podman socket exists:
-
-```bash
-$ ls /run/user/${UID}/podman
-podman.sock
-```
-
-If you’re running the system service as root, podman.sock will be found in /run/podman:
-```bash
-# ls /run/podman
-podman.sock
-```
-
-
-### Connect to the Podman system service <a name="connect-service"></a>
-First, you need to create a connection that connects to the system service.
-The critical piece of information for setting up a new connection is the endpoint.
-The endpoint comes in the form of an URI (method:/path/to/socket). For example,
-to connect to the local rootful socket the URI would be `unix:/run/podman/podman.sock`
-and for a rootless user it would be `unix:$(XDG_RUNTIME_DIR)/podman/podman.sock`,
-typically: `unix:/run/user/${UID}/podman/podman.sock`.
-
-
-The following Go example snippet shows how to set up a connection for a rootless user.
-```Go
-package main
-
-import (
- "context"
- "fmt"
- "os"
-
- "github.com/containers/libpod/v3/libpod/define"
- "github.com/containers/libpod/v3/pkg/bindings"
- "github.com/containers/libpod/v3/pkg/bindings/containers"
- "github.com/containers/libpod/v3/pkg/bindings/images"
- "github.com/containers/libpod/v3/pkg/domain/entities"
- "github.com/containers/libpod/v3/pkg/specgen"
-)
-
-func main() {
- fmt.Println("Welcome to the Podman Go bindings tutorial")
-
- // Get Podman socket location
- sock_dir := os.Getenv("XDG_RUNTIME_DIR")
- socket := "unix:" + sock_dir + "/podman/podman.sock"
-
- // Connect to Podman socket
- connText, err := bindings.NewConnection(context.Background(), socket)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-}
-```
-
-The `connText` variable received from the NewConnection function is of type
-context.Context(). In subsequent uses of the bindings, you will use this context
-to direct the bindings to your connection. This can be seen in the examples below.
-
-### Pull an image <a name="pull-images"></a>
-
-Next, we will pull a couple of images using the images.Pull() binding.
-This binding takes three arguments:
- - The context variable created by the bindings.NewConnection() call in the first example
- - The image name
- - Options for image pull
-
-**Append the following lines to your function:**
-
-```Go
- // Pull Busybox image (Sample 1)
- fmt.Println("Pulling Busybox image...")
- _, err = images.Pull(connText, "docker.io/busybox", &images.PullOptions{})
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-
- // Pull Fedora image (Sample 2)
- rawImage := "registry.fedoraproject.org/fedora:latest"
- fmt.Println("Pulling Fedora image...")
- _, err = images.Pull(connText, rawImage, &images.PullOptions{})
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-```
-
-**Run it:**
-
-```bash
-$ go run main.go
-Welcome to the Podman Go bindings tutorial
-Pulling Busybox image...
-Pulling Fedora image...
-$
-```
-
-The system service side should echo messages like so:
-
-```bash
-Trying to pull docker.io/busybox...
-Getting image source signatures
-Copying blob 61c5ed1cbdf8 [--------------------------------------] 0.0b / 0.0b
-Copying config 018c9d7b79 done
-Writing manifest to image destination
-Storing signatures
-Trying to pull registry.fedoraproject.org/fedora:latest...
-Getting image source signatures
-Copying blob dd9f43919ba0 [--------------------------------------] 0.0b / 0.0b
-Copying config 00ff39a8bf done
-Writing manifest to image destination
-Storing signatures
-```
-
-
-### List images <a name="list-images"></a>
-Next, we will pull an image using the images.List() binding.
-This binding takes three arguments:
- - The context variable created earlier
- - An optional bool 'all'
- - An optional map of filters
-
-**Append the following lines to your function:**
-
-```Go
- // List images
- imageSummary, err := images.List(connText, &images.ListOptions{})
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
- var names []string
- for _, i := range imageSummary {
- names = append(names, i.RepoTags...)
- }
- fmt.Println("Listing images...")
- fmt.Println(names)
-```
-
-**Run it:**
-
-```bash
-$ go run main.go
-Welcome to the Podman Go bindings tutorial
-Pulling Busybox image...
-Pulling Fedora image...
-Listing images...
-[docker.io/library/busybox:latest registry.fedoraproject.org/fedora:latest]
-$
-```
-
-
-### Create and Start a Container from an Image <a name="create-start-container"></a>
-
-To create the container spec, we use specgen.NewSpecGenerator() followed by
-calling containers.CreateWithSpec() to actually create a new container.
-specgen.NewSpecGenerator() takes 2 arguments:
- - name of the image
- - whether it's a rootfs
-
-containers.CreateWithSpec() takes 2 arguments:
- - the context created earlier
- - the spec created by NewSpecGenerator
-
-Next, the container is actually started using the containers.Start() binding.
-containers.Start() takes three arguments:
- - the context
- - the name or ID of the container created
- - an optional parameter for detach keys
-
-After the container is started, it's a good idea to ensure the container is
-in a running state before you proceed with further operations.
-The containers.Wait() takes care of that.
-containers.Wait() takes three arguments:
- - the context
- - the name or ID of the container created
- - container state (running/paused/stopped)
-
-**Append the following lines to your function:**
-
-```Go
- // Container create
- s := specgen.NewSpecGenerator(rawImage, false)
- s.Terminal = true
- r, err := containers.CreateWithSpec(connText, s, nil)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-
- // Container start
- fmt.Println("Starting Fedora container...")
- err = containers.Start(connText, r.ID, nil)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-
- running := define.ContainerStateRunning
- _, err = containers.Wait(connText, r.ID, &containers.WaitOptions{Condition: []define.ContainerStatus{running}})
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-```
-
-**Run it:**
-
-```bash
-$ go run main.go
-Welcome to the Podman Go bindings tutorial
-Pulling image...
-Starting Fedora container...
-$
-```
-
-Check if the container is running:
-
-```bash
-$ podman ps
-CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
-665831d31e90 registry.fedoraproject.org/fedora:latest /bin/bash Less than a second ago Up Less than a second ago dazzling_mclean
-$
-```
-
-
-### List Containers <a name="list-containers"></a>
-
-Containers can be listed using the containers.List() binding.
-containers.List() takes seven arguments:
- - the context
- - output filters
- - boolean to show all containers, by default only running containers are listed
- - number of latest created containers, all states (running/paused/stopped)
- - boolean to print pod information
- - boolean to print rootfs size
- - boolean to print oci runtime and container state
-
-**Append the following lines to your function:**
-
-```Go
- // Container list
- var latestContainers = 1
- containerLatestList, err := containers.List(connText, &containers.ListOptions{Last: &latestContainers})
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
- fmt.Printf("Latest container is %s\n", containerLatestList[0].Names[0])
-```
-
-**Run it:**
-
-```bash
-$ go run main.go
-Welcome to the Podman Go bindings tutorial
-Pulling Busybox image...
-Pulling Fedora image...
-Listing images...
-[docker.io/library/busybox:latest registry.fedoraproject.org/fedora:latest]
-Starting Fedora container...
-Latest container is dazzling_mclean
-$
-```
-
-
-### Inspect Container <a name="inspect-container"></a>
-Containers can be inspected using the containers.Inspect() binding.
-containers.Inspect() takes 3 arguments:
- - context
- - image name or ID
- - optional boolean to check for container size
-
-
-**Append the following lines to your function:**
-
-```Go
- // Container inspect
- ctrData, err := containers.Inspect(connText, r.ID, nil)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
- fmt.Printf("Container uses image %s\n", ctrData.ImageName)
- fmt.Printf("Container running status is %s\n", ctrData.State.Status)
-```
-
-**Run it:**
-
-```bash
-$ go run main.go
-Welcome to the Podman Go bindings tutorial
-Pulling Busybox image...
-Pulling Fedora image...
-Listing images...
-[docker.io/library/busybox:latest registry.fedoraproject.org/fedora:latest]
-Starting Fedora container...
-Latest container is peaceful_noether
-Fedora Container uses image registry.fedoraproject.org/fedora:latest
-Fedora Container running status is running
-$
-```
-
-
-### Stop Container <a name="stop-container"></a>
-
-A container can be stopped by the containers.Stop() binding.
-containers.Stop() takes 3 arguments:
- - context
- - image name or ID
- - optional timeout
-
-**Append the following lines to your function:**
-
-```Go
- // Container stop
- fmt.Println("Stopping the container...")
- err = containers.Stop(connText, r.ID, nil)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
- ctrData, err = containers.Inspect(connText, r.ID, nil)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
- fmt.Printf("Container running status is now %s\n", ctrData.State.Status)
-```
-
-**Run it:**
-
-```bash
-$ go run main.go
-Welcome to the Podman Go bindings tutorial
-Pulling Busybox image...
-Pulling Fedora image...
-Listing images...
-[docker.io/library/busybox:latest registry.fedoraproject.org/fedora:latest]
-Starting Fedora container...
-Latest container is peaceful_noether
-Fedora Container uses image registry.fedoraproject.org/fedora:latest
-Fedora Container running status is running
-Stopping Fedora container...
-Container running status is now exited
-```
-
-
-### Debugging tips <a name="debugging-tips"></a>
-
-To debug in a development setup, you can start the Podman system service
-in debug mode like so:
-
-```bash
-$ podman --log-level=debug system service -t 0
-```
-
-The `--log-level=debug` echoes all the logged requests and is useful to
-trace the execution path at a finer granularity. A snippet of a sample run looks like:
-
-```bash
-INFO[0000] podman filtering at log level debug
-DEBU[0000] Called service.PersistentPreRunE(podman --log-level=debug system service -t0)
-DEBU[0000] Ignoring libpod.conf EventsLogger setting "/home/lsm5/.config/containers/containers.conf". Use "journald" if you want to change this setting and remove libpod.conf files.
-DEBU[0000] Reading configuration file "/usr/share/containers/containers.conf"
-DEBU[0000] Merged system config "/usr/share/containers/containers.conf": {Editors note: the remainder of this line was removed due to Jekyll formatting errors.}
-DEBU[0000] Using conmon: "/usr/bin/conmon"
-DEBU[0000] Initializing boltdb state at /home/lsm5/.local/share/containers/storage/libpod/bolt_state.db
-DEBU[0000] Overriding run root "/run/user/1000/containers" with "/run/user/1000" from database
-DEBU[0000] Using graph driver overlay
-DEBU[0000] Using graph root /home/lsm5/.local/share/containers/storage
-DEBU[0000] Using run root /run/user/1000
-DEBU[0000] Using static dir /home/lsm5/.local/share/containers/storage/libpod
-DEBU[0000] Using tmp dir /run/user/1000/libpod/tmp
-DEBU[0000] Using volume path /home/lsm5/.local/share/containers/storage/volumes
-DEBU[0000] Set libpod namespace to ""
-DEBU[0000] Not configuring container store
-DEBU[0000] Initializing event backend file
-DEBU[0000] using runtime "/usr/bin/runc"
-DEBU[0000] using runtime "/usr/bin/crun"
-WARN[0000] Error initializing configured OCI runtime kata: no valid executable found for OCI runtime kata: invalid argument
-DEBU[0000] using runtime "/usr/bin/crun"
-INFO[0000] Setting parallel job count to 25
-INFO[0000] podman filtering at log level debug
-DEBU[0000] Called service.PersistentPreRunE(podman --log-level=debug system service -t0)
-DEBU[0000] Ignoring libpod.conf EventsLogger setting "/home/lsm5/.config/containers/containers.conf". Use "journald" if you want to change this setting and remove libpod.conf files.
-DEBU[0000] Reading configuration file "/usr/share/containers/containers.conf"
-```
-
-If the Podman system service has been started via systemd socket activation,
-you can view the logs using journalctl. The logs after a sample run look like so:
-
-```bash
-$ journalctl --user --no-pager -u podman.socket
--- Reboot --
-Jul 22 13:50:40 nagato.nanadai.me systemd[1048]: Listening on Podman API Socket.
-$
-```
-
-```bash
-$ journalctl --user --no-pager -u podman.service
-Jul 22 13:50:53 nagato.nanadai.me systemd[1048]: Starting Podman API Service...
-Jul 22 13:50:54 nagato.nanadai.me podman[1527]: time="2020-07-22T13:50:54-04:00" level=error msg="Error refreshing volume 38480630a8bdaa3e1a0ebd34c94038591b0d7ad994b37be5b4f2072bb6ef0879: error acquiring lock 0 for volume 38480630a8bdaa3e1a0ebd34c94038591b0d7ad994b37be5b4f2072bb6ef0879: file exists"
-Jul 22 13:50:54 nagato.nanadai.me podman[1527]: time="2020-07-22T13:50:54-04:00" level=error msg="Error refreshing volume 47d410af4d762a0cc456a89e58f759937146fa3be32b5e95a698a1d4069f4024: error acquiring lock 0 for volume 47d410af4d762a0cc456a89e58f759937146fa3be32b5e95a698a1d4069f4024: file exists"
-Jul 22 13:50:54 nagato.nanadai.me podman[1527]: time="2020-07-22T13:50:54-04:00" level=error msg="Error refreshing volume 86e73f082e344dad38c8792fb86b2017c4f133f2a8db87f239d1d28a78cf0868: error acquiring lock 0 for volume 86e73f082e344dad38c8792fb86b2017c4f133f2a8db87f239d1d28a78cf0868: file exists"
-Jul 22 13:50:54 nagato.nanadai.me podman[1527]: time="2020-07-22T13:50:54-04:00" level=error msg="Error refreshing volume 9a16ea764be490a5563e384d9074ab0495e4d9119be380c664037d6cf1215631: error acquiring lock 0 for volume 9a16ea764be490a5563e384d9074ab0495e4d9119be380c664037d6cf1215631: file exists"
-Jul 22 13:50:54 nagato.nanadai.me podman[1527]: time="2020-07-22T13:50:54-04:00" level=error msg="Error refreshing volume bfd6b2a97217f8655add13e0ad3f6b8e1c79bc1519b7a1e15361a107ccf57fc0: error acquiring lock 0 for volume bfd6b2a97217f8655add13e0ad3f6b8e1c79bc1519b7a1e15361a107ccf57fc0: file exists"
-Jul 22 13:50:54 nagato.nanadai.me podman[1527]: time="2020-07-22T13:50:54-04:00" level=error msg="Error refreshing volume f9b9f630982452ebcbed24bd229b142fbeecd5d4c85791fca440b21d56fef563: error acquiring lock 0 for volume f9b9f630982452ebcbed24bd229b142fbeecd5d4c85791fca440b21d56fef563: file exists"
-Jul 22 13:50:54 nagato.nanadai.me podman[1527]: Trying to pull registry.fedoraproject.org/fedora:latest...
-Jul 22 13:50:55 nagato.nanadai.me podman[1527]: Getting image source signatures
-Jul 22 13:50:55 nagato.nanadai.me podman[1527]: Copying blob sha256:dd9f43919ba05f05d4f783c31e83e5e776c4f5d29dd72b9ec5056b9576c10053
-Jul 22 13:50:55 nagato.nanadai.me podman[1527]: Copying config sha256:00ff39a8bf19f810a7e641f7eb3ddc47635913a19c4996debd91fafb6b379069
-Jul 22 13:50:55 nagato.nanadai.me podman[1527]: Writing manifest to image destination
-Jul 22 13:50:55 nagato.nanadai.me podman[1527]: Storing signatures
-Jul 22 13:50:55 nagato.nanadai.me systemd[1048]: podman.service: unit configures an IP firewall, but not running as root.
-Jul 22 13:50:55 nagato.nanadai.me systemd[1048]: (This warning is only shown for the first unit using IP firewalling.)
-Jul 22 13:51:15 nagato.nanadai.me systemd[1048]: podman.service: Succeeded.
-Jul 22 13:51:15 nagato.nanadai.me systemd[1048]: Finished Podman API Service.
-Jul 22 13:51:15 nagato.nanadai.me systemd[1048]: podman.service: Consumed 1.339s CPU time.
-$
-```
-
-
-## Wrap Up
-Podman provides a set of Go bindings to allow developers to integrate Podman
-functionality conveniently in their Go application. These Go bindings require
-the Podman system service to be running in the background and this can easily
-be achieved using systemd socket activation. Once set up, you are able to use a
-set of Go based bindings to create, maintain and monitor your container images,
-containers and pods in a way which fits very nicely in many production environments.
-
-
-## References
-- Podman is available for most major distributions along with macOS and Windows.
-Installation details are available on the [Podman official website](https://podman.io/getting-started/).
-
-- Documentation can be found at the [Podman Docs page](https://docs.podman.io).
-It also includes a section on the [RESTful API](https://docs.podman.io/en/latest/Reference.html).
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 1b775a4f3..48b0c495c 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -111,13 +111,33 @@ type RootlessCNI struct {
lock lockfile.Locker
}
+// getPath will join the given path to the rootless cni dir
+func (r *RootlessCNI) getPath(path string) string {
+ return filepath.Join(r.dir, path)
+}
+
+// Do - run the given function in the rootless cni ns.
+// It does not lock the rootlessCNI lock, the caller
+// should only lock when needed, e.g. for cni operations.
func (r *RootlessCNI) Do(toRun func() error) error {
err := r.ns.Do(func(_ ns.NetNS) error {
- // before we can run the given function
- // we have to setup all mounts correctly
-
- // create a new mount namespace
- // this should happen inside the netns thread
+ // Before we can run the given function,
+ // we have to setup all mounts correctly.
+
+ // The order of the mounts is IMPORTANT.
+ // The idea of the extra mount ns is to make /run and /var/lib/cni writeable
+ // for the cni plugins but not affecting the podman user namespace.
+ // Because the plugins also need access to XDG_RUNTIME_DIR/netns some special setup is needed.
+
+ // The following bind mounts are needed
+ // 1. XDG_RUNTIME_DIR/netns -> XDG_RUNTIME_DIR/rootless-cni/XDG_RUNTIME_DIR/netns
+ // 2. /run/systemd -> XDG_RUNTIME_DIR/rootless-cni/run/systemd (only if it exists)
+ // 3. XDG_RUNTIME_DIR/rootless-cni/resolv.conf -> /etc/resolv.conf or XDG_RUNTIME_DIR/rootless-cni/run/symlink/target
+ // 4. XDG_RUNTIME_DIR/rootless-cni/var/lib/cni -> /var/lib/cni (if /var/lib/cni does not exists use the parent dir)
+ // 5. XDG_RUNTIME_DIR/rootless-cni/run -> /run
+
+ // Create a new mount namespace,
+ // this must happen inside the netns thread.
err := unix.Unshare(unix.CLONE_NEWNS)
if err != nil {
return errors.Wrapf(err, "cannot create a new mount namespace")
@@ -127,33 +147,55 @@ func (r *RootlessCNI) Do(toRun func() error) error {
if err != nil {
return errors.Wrap(err, "could not get network namespace directory")
}
- newNetNsDir := filepath.Join(r.dir, netNsDir)
- // mount the netns into the new run to keep them accessible
- // otherwise cni setup will fail because it cannot access the netns files
+ newNetNsDir := r.getPath(netNsDir)
+ // 1. Mount the netns into the new run to keep them accessible.
+ // Otherwise cni setup will fail because it cannot access the netns files.
err = unix.Mount(netNsDir, newNetNsDir, "none", unix.MS_BIND|unix.MS_SHARED|unix.MS_REC, "")
if err != nil {
return errors.Wrap(err, "failed to mount netns directory for rootless cni")
}
- // mount resolv.conf to make use of the host dns
- err = unix.Mount(filepath.Join(r.dir, "resolv.conf"), "/etc/resolv.conf", "none", unix.MS_BIND, "")
- if err != nil {
- return errors.Wrap(err, "failed to mount resolv.conf for rootless cni")
- }
-
- // also keep /run/systemd if it exists
- // many files are symlinked into this dir, for example /dev/log
+ // 2. Also keep /run/systemd if it exists.
+ // Many files are symlinked into this dir, for example /dev/log.
runSystemd := "/run/systemd"
_, err = os.Stat(runSystemd)
if err == nil {
- newRunSystemd := filepath.Join(r.dir, runSystemd[1:])
+ newRunSystemd := r.getPath(runSystemd)
err = unix.Mount(runSystemd, newRunSystemd, "none", unix.MS_BIND|unix.MS_REC, "")
if err != nil {
return errors.Wrap(err, "failed to mount /run/systemd directory for rootless cni")
}
}
- // cni plugins need access to /var/lib/cni and /run
+ // 3. On some distros /etc/resolv.conf is symlinked to somewhere under /run.
+ // Because the kernel will follow the symlink before mounting, it is not
+ // possible to mount a file at /etc/resolv.conf. We have to ensure that
+ // the link target will be available in the mount ns.
+ // see: https://github.com/containers/podman/issues/10855
+ resolvePath := "/etc/resolv.conf"
+ resolvePath, err = filepath.EvalSymlinks(resolvePath)
+ if err != nil {
+ return err
+ }
+ if strings.HasPrefix(resolvePath, "/run/") {
+ resolvePath = r.getPath(resolvePath)
+ err = os.MkdirAll(filepath.Dir(resolvePath), 0700)
+ if err != nil {
+ return errors.Wrap(err, "failed to create rootless-cni resolv.conf directory")
+ }
+ // we want to bind mount on this file so we have to create the file first
+ _, err = os.OpenFile(resolvePath, os.O_CREATE|os.O_RDONLY, 0700)
+ if err != nil {
+ return errors.Wrap(err, "failed to create rootless-cni resolv.conf file")
+ }
+ }
+ // mount resolv.conf to make use of the host dns
+ err = unix.Mount(r.getPath("resolv.conf"), resolvePath, "none", unix.MS_BIND, "")
+ if err != nil {
+ return errors.Wrap(err, "failed to mount resolv.conf for rootless cni")
+ }
+
+ // 4. CNI plugins need access to /var/lib/cni and /run
varDir := ""
varTarget := persistentCNIDir
// we can only mount to a target dir which exists, check /var/lib/cni recursively
@@ -161,10 +203,10 @@ func (r *RootlessCNI) Do(toRun func() error) error {
// configs under /var/custom and this would break
for {
if _, err := os.Stat(varTarget); err == nil {
- varDir = filepath.Join(r.dir, strings.TrimPrefix(varTarget, "/"))
+ varDir = r.getPath(varTarget)
break
}
- varTarget = filepath.Base(varTarget)
+ varTarget = filepath.Dir(varTarget)
if varTarget == "/" {
break
}
@@ -177,8 +219,9 @@ func (r *RootlessCNI) Do(toRun func() error) error {
if err != nil {
return errors.Wrapf(err, "failed to mount %s for rootless cni", varTarget)
}
- runDir := filepath.Join(r.dir, "run")
- // recursive mount to keep the netns mount
+
+ // 5. Mount the new prepared run dir to /run, it has to be recursive to keep the other bind mounts.
+ runDir := r.getPath("run")
err = unix.Mount(runDir, "/run", "none", unix.MS_BIND|unix.MS_REC, "")
if err != nil {
return errors.Wrap(err, "failed to mount /run for rootless cni")
@@ -221,7 +264,7 @@ func (r *RootlessCNI) Cleanup(runtime *Runtime) error {
// make sure the the cni results (cache) dir is empty
// libpod instances with another root dir are not covered by the check above
// this allows several libpod instances to use the same rootless cni ns
- contents, err := ioutil.ReadDir(filepath.Join(r.dir, "var/lib/cni/results"))
+ contents, err := ioutil.ReadDir(r.getPath("var/lib/cni/results"))
if (err == nil && len(contents) == 0) || os.IsNotExist(err) {
logrus.Debug("Cleaning up rootless cni namespace")
err = netns.UnmountNS(r.ns)
@@ -233,7 +276,7 @@ func (r *RootlessCNI) Cleanup(runtime *Runtime) error {
if err != nil {
logrus.Error(err)
}
- b, err := ioutil.ReadFile(filepath.Join(r.dir, "rootless-cni-slirp4netns.pid"))
+ b, err := ioutil.ReadFile(r.getPath("rootless-cni-slirp4netns.pid"))
if err == nil {
var i int
i, err = strconv.Atoi(string(b))
@@ -395,10 +438,15 @@ func (r *Runtime) GetRootlessCNINetNs(new bool) (*RootlessCNI, error) {
if err != nil {
return nil, err
}
+ conf, err = resolvconf.FilterResolvDNS(conf.Content, netOptions.enableIPv6, true)
+ if err != nil {
+ return nil, err
+ }
searchDomains := resolvconf.GetSearchDomains(conf.Content)
dnsOptions := resolvconf.GetOptions(conf.Content)
+ nameServers := resolvconf.GetNameservers(conf.Content)
- _, err = resolvconf.Build(filepath.Join(cniDir, "resolv.conf"), []string{resolveIP.String()}, searchDomains, dnsOptions)
+ _, err = resolvconf.Build(filepath.Join(cniDir, "resolv.conf"), append([]string{resolveIP.String()}, nameServers...), searchDomains, dnsOptions)
if err != nil {
return nil, errors.Wrap(err, "failed to create rootless cni resolv.conf")
}
@@ -500,7 +548,9 @@ func (r *Runtime) setUpOCICNIPod(podNetwork ocicni.PodNetwork) ([]ocicni.NetResu
// rootlessCNINS is nil if we are root
if rootlessCNINS != nil {
// execute the cni setup in the rootless net ns
+ rootlessCNINS.lock.Lock()
err = rootlessCNINS.Do(setUpPod)
+ rootlessCNINS.lock.Unlock()
} else {
err = setUpPod()
}
@@ -712,7 +762,9 @@ func (r *Runtime) teardownOCICNIPod(podNetwork ocicni.PodNetwork) error {
// rootlessCNINS is nil if we are root
if rootlessCNINS != nil {
// execute the cni setup in the rootless net ns
+ rootlessCNINS.lock.Lock()
err = rootlessCNINS.Do(tearDownPod)
+ rootlessCNINS.lock.Unlock()
if err == nil {
err = rootlessCNINS.Cleanup(r)
}
diff --git a/pkg/bindings/README.md b/pkg/bindings/README.md
index 6fd7d7831..f41304e0f 100644
--- a/pkg/bindings/README.md
+++ b/pkg/bindings/README.md
@@ -154,3 +154,80 @@ func main() {
fmt.Println("Container started.")
}
```
+
+## Debugging tips <a name="debugging-tips"></a>
+
+To debug in a development setup, you can start the Podman system service
+in debug mode like:
+
+```bash
+$ podman --log-level=debug system service -t 0
+```
+
+The `--log-level=debug` echoes all the logged requests and is useful to
+trace the execution path at a finer granularity. A snippet of a sample run looks like:
+
+```bash
+INFO[0000] podman filtering at log level debug
+DEBU[0000] Called service.PersistentPreRunE(podman --log-level=debug system service -t0)
+DEBU[0000] Ignoring libpod.conf EventsLogger setting "/home/lsm5/.config/containers/containers.conf". Use "journald" if you want to change this setting and remove libpod.conf files.
+DEBU[0000] Reading configuration file "/usr/share/containers/containers.conf"
+DEBU[0000] Merged system config "/usr/share/containers/containers.conf": {Editors note: the remainder of this line was removed due to Jekyll formatting errors.}
+DEBU[0000] Using conmon: "/usr/bin/conmon"
+DEBU[0000] Initializing boltdb state at /home/lsm5/.local/share/containers/storage/libpod/bolt_state.db
+DEBU[0000] Overriding run root "/run/user/1000/containers" with "/run/user/1000" from database
+DEBU[0000] Using graph driver overlay
+DEBU[0000] Using graph root /home/lsm5/.local/share/containers/storage
+DEBU[0000] Using run root /run/user/1000
+DEBU[0000] Using static dir /home/lsm5/.local/share/containers/storage/libpod
+DEBU[0000] Using tmp dir /run/user/1000/libpod/tmp
+DEBU[0000] Using volume path /home/lsm5/.local/share/containers/storage/volumes
+DEBU[0000] Set libpod namespace to ""
+DEBU[0000] Not configuring container store
+DEBU[0000] Initializing event backend file
+DEBU[0000] using runtime "/usr/bin/runc"
+DEBU[0000] using runtime "/usr/bin/crun"
+WARN[0000] Error initializing configured OCI runtime kata: no valid executable found for OCI runtime kata: invalid argument
+DEBU[0000] using runtime "/usr/bin/crun"
+INFO[0000] Setting parallel job count to 25
+INFO[0000] podman filtering at log level debug
+DEBU[0000] Called service.PersistentPreRunE(podman --log-level=debug system service -t0)
+DEBU[0000] Ignoring libpod.conf EventsLogger setting "/home/lsm5/.config/containers/containers.conf". Use "journald" if you want to change this setting and remove libpod.conf files.
+DEBU[0000] Reading configuration file "/usr/share/containers/containers.conf"
+```
+
+If the Podman system service has been started via systemd socket activation,
+you can view the logs using journalctl. The logs after a sample run look like:
+
+```bash
+$ journalctl --user --no-pager -u podman.socket
+-- Reboot --
+Jul 22 13:50:40 nagato.nanadai.me systemd[1048]: Listening on Podman API Socket.
+$
+```
+
+```bash
+$ journalctl --user --no-pager -u podman.service
+Jul 22 13:50:53 nagato.nanadai.me systemd[1048]: Starting Podman API Service...
+Jul 22 13:50:54 nagato.nanadai.me podman[1527]: time="2020-07-22T13:50:54-04:00" level=error msg="Error refreshing volume 38480630a8bdaa3e1a0ebd34c94038591b0d7ad994b37be5b4f2072bb6ef0879: error acquiring lock 0 for volume 38480630a8bdaa3e1a0ebd34c94038591b0d7ad994b37be5b4f2072bb6ef0879: file exists"
+Jul 22 13:50:54 nagato.nanadai.me podman[1527]: time="2020-07-22T13:50:54-04:00" level=error msg="Error refreshing volume 47d410af4d762a0cc456a89e58f759937146fa3be32b5e95a698a1d4069f4024: error acquiring lock 0 for volume 47d410af4d762a0cc456a89e58f759937146fa3be32b5e95a698a1d4069f4024: file exists"
+Jul 22 13:50:54 nagato.nanadai.me podman[1527]: time="2020-07-22T13:50:54-04:00" level=error msg="Error refreshing volume 86e73f082e344dad38c8792fb86b2017c4f133f2a8db87f239d1d28a78cf0868: error acquiring lock 0 for volume 86e73f082e344dad38c8792fb86b2017c4f133f2a8db87f239d1d28a78cf0868: file exists"
+Jul 22 13:50:54 nagato.nanadai.me podman[1527]: time="2020-07-22T13:50:54-04:00" level=error msg="Error refreshing volume 9a16ea764be490a5563e384d9074ab0495e4d9119be380c664037d6cf1215631: error acquiring lock 0 for volume 9a16ea764be490a5563e384d9074ab0495e4d9119be380c664037d6cf1215631: file exists"
+Jul 22 13:50:54 nagato.nanadai.me podman[1527]: time="2020-07-22T13:50:54-04:00" level=error msg="Error refreshing volume bfd6b2a97217f8655add13e0ad3f6b8e1c79bc1519b7a1e15361a107ccf57fc0: error acquiring lock 0 for volume bfd6b2a97217f8655add13e0ad3f6b8e1c79bc1519b7a1e15361a107ccf57fc0: file exists"
+Jul 22 13:50:54 nagato.nanadai.me podman[1527]: time="2020-07-22T13:50:54-04:00" level=error msg="Error refreshing volume f9b9f630982452ebcbed24bd229b142fbeecd5d4c85791fca440b21d56fef563: error acquiring lock 0 for volume f9b9f630982452ebcbed24bd229b142fbeecd5d4c85791fca440b21d56fef563: file exists"
+Jul 22 13:50:54 nagato.nanadai.me podman[1527]: Trying to pull registry.fedoraproject.org/fedora:latest...
+Jul 22 13:50:55 nagato.nanadai.me podman[1527]: Getting image source signatures
+Jul 22 13:50:55 nagato.nanadai.me podman[1527]: Copying blob sha256:dd9f43919ba05f05d4f783c31e83e5e776c4f5d29dd72b9ec5056b9576c10053
+Jul 22 13:50:55 nagato.nanadai.me podman[1527]: Copying config sha256:00ff39a8bf19f810a7e641f7eb3ddc47635913a19c4996debd91fafb6b379069
+Jul 22 13:50:55 nagato.nanadai.me podman[1527]: Writing manifest to image destination
+Jul 22 13:50:55 nagato.nanadai.me podman[1527]: Storing signatures
+Jul 22 13:50:55 nagato.nanadai.me systemd[1048]: podman.service: unit configures an IP firewall, but not running as root.
+Jul 22 13:50:55 nagato.nanadai.me systemd[1048]: (This warning is only shown for the first unit using IP firewalling.)
+Jul 22 13:51:15 nagato.nanadai.me systemd[1048]: podman.service: Succeeded.
+Jul 22 13:51:15 nagato.nanadai.me systemd[1048]: Finished Podman API Service.
+Jul 22 13:51:15 nagato.nanadai.me systemd[1048]: podman.service: Consumed 1.339s CPU time.
+$
+```
+
+You can also verify that the information being passed back and forth is correct by putting
+with a tool like `socat`, which can dump what the socket is seeing.