summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--docs/MANPAGE_SYNTAX.md34
-rw-r--r--docs/source/markdown/podman-attach.1.md7
-rw-r--r--docs/source/markdown/podman-commit.1.md12
-rw-r--r--docs/source/markdown/podman-completion.1.md42
-rw-r--r--docs/source/markdown/podman-container-checkpoint.1.md86
-rw-r--r--docs/source/markdown/podman-container-cleanup.1.md46
-rw-r--r--docs/source/markdown/podman-container-exists.1.md24
-rw-r--r--docs/source/markdown/podman.1.md4
-rw-r--r--libpod/container_exec.go67
-rw-r--r--libpod/container_internal.go2
-rw-r--r--libpod/events.go39
-rw-r--r--libpod/events/config.go2
-rw-r--r--libpod/events/events.go2
-rw-r--r--libpod/networking_linux.go4
-rw-r--r--libpod/options.go13
-rw-r--r--libpod/volume_internal.go19
-rw-r--r--pkg/api/handlers/compat/images_build.go8
-rw-r--r--pkg/domain/infra/abi/containers.go36
-rw-r--r--pkg/domain/infra/abi/parse/parse.go4
-rw-r--r--test/apiv2/10-images.at35
-rwxr-xr-xtest/compose/test-compose2
-rw-r--r--test/e2e/build_test.go34
-rw-r--r--test/e2e/run_volume_test.go32
24 files changed, 388 insertions, 168 deletions
diff --git a/Makefile b/Makefile
index f2b9d87de..3e40881f3 100644
--- a/Makefile
+++ b/Makefile
@@ -437,7 +437,7 @@ $(MANPAGES): %: %.md .install.md2man docdir
-e 's/\[\(podman[^]]*\)\]/\1/g' \
-e 's/\[\([^]]*\)](http[^)]\+)/\1/g' \
-e 's;<\(/\)\?\(a\|a\s\+[^>]*\|sup\)>;;g' \
- -e 's/\\$// /g' $< | \
+ -e 's/\\$$/ /g' $< | \
$(GOMD2MAN) -in /dev/stdin -out $(subst source/markdown,build/man,$@)
.PHONY: docdir
diff --git a/docs/MANPAGE_SYNTAX.md b/docs/MANPAGE_SYNTAX.md
index c9b677688..9794a0c3d 100644
--- a/docs/MANPAGE_SYNTAX.md
+++ b/docs/MANPAGE_SYNTAX.md
@@ -4,7 +4,7 @@
podman\-command - short description
## SYNOPSIS
-(Shows the command structure.)
+(Shows the command structure. If the command can be written in two different ways, both of them have to be shown.)
**podman command** [*optional*] *mandatory value*
@@ -16,7 +16,7 @@ podman\-command - short description
**podman subcommand command** [*optional*] *value1* | *value2*
-(If an optinal value follows a mandatory one.)
+(If an optional value follows a mandatory one.)
**podman command** [*optional*] *value1* | *value2* [*optional*]
@@ -33,23 +33,23 @@ podman\-command - short description
Example sentence: The command **podman command** is an example command.
Commands or files that are quoted from other podman manpages or podman repositories have to be linked to those. Non-podman commands are not to be linked.\
-Example sentence: You can use **[podman-run](podman-run.1.md)** or **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for the problem.
+Example sentence: Use **[podman-run](podman-run.1.md)** or **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for the problem.
-It should also be specified if the command can only be run as root. In addition, it should be described when a command, OPTION, or other content cannot be executed with the remote client or in combination with other commands, OPTIONS, or content. In this case, the following sentence is put at the end of a command, OPTION, or content: *IMPORTANT: This option/command/other is not available with the command/OPTION/content/remote Podman client*. For a command, this should be done in the DESCRIPTION section. For the OPTIONS, it should be done in the DESCRIPTION of the specified OPTION. Do not use pronouns in the man pages, especially the word `you`.
+It should also be specified if the command can only be run as root. In addition, it should be described when a command, OPTION, or other content cannot be executed with the remote client or in combination with other commands, OPTIONS, or content. In this case, the following sentence is put at the end of a command, OPTION, or content: *IMPORTANT: This OPTION/command/other is not available with the command/OPTION/content/remote Podman client*. For a command, this should be done in the DESCRIPTION section. For the OPTIONS, it should be done in the DESCRIPTION of the specified OPTION. Do not use pronouns in the man pages, especially the word `you`.
## OPTIONS
All flags are referred to as OPTIONS. The term flags should not be used. All OPTIONS are listed in this section. OPTIONS that appear in descriptions of other OPTIONS and sections retain their appearance, for example: **--exit**.
OPTIONS that are quoted from other podman manpages or podman repositories have to be linked to those.\
-Example sentence: You can use **[podman-generate-systemd --new](podman-generate-systemd.1.md#--new)** for the problem.
+Example sentence: Use **[podman-generate-systemd --new](podman-generate-systemd.1.md#--new)** for the problem.
Each OPTION should be explained to the fullest extent below the OPTION itself. Each OPTION is behind an H4-header (`####`). If the OPTION has a default argument, it has to be explained in the description of the OPTION. If the OPTION is also not available with the remote client, the sentence about the default argument should the second to last sentence.
#### **--version**, **-v**
-OPTIONS can be put after the command in two different ways. Eather the long version with **--option** or as the short version **-o**. If there are two ways to write an OPTION they are separated by a comma. If there are two versions of one command the long version is always shown in front.\
-Example: The default is **false**. *IMPORTANT: This option is not available with the remote Podman client*.
+OPTIONS can be put after the command in two different ways. Either the long version with **--option** or as the short version **-o**. If there are two ways to write an OPTION they are separated by a comma. If there are two versions of one command the long version is always shown in front.\
+Example: The default is **false**. *IMPORTANT: This OPTION is not available with the remote Podman client*.
#### **--exit**
@@ -57,7 +57,7 @@ An example of an OPTION that has only one possible structure. Thus, it cannot be
#### **--answer**=, **-a**=**active** | *disable*
-The "answer" option above is an example of an OPTION that accepts two possible arguments as inputs. If there is a default argument that is selected when the OPTION is not used in the command, it is shown in **bold**. If the OPTION is used it must include an argument afterwards. It must always be ensured that the standard argument is in the first position after the OPTION. In this example, there are two different ways to execute the command. Both possible OPTIONS have to be shown with the arguments following them. The default value is shown as **active**.
+The "answer" OPTION above is an example of an OPTION that accepts two possible arguments as inputs. If there is a default argument that is selected when the OPTION is not used in the command, it is shown in **bold**. If the OPTION is used it must include an argument afterwards. It must always be ensured that the standard argument is in the first position after the OPTION. In this example, there are two different ways to execute the command. Both possible OPTIONS have to be shown with the arguments following them. The default value is shown as **active**.
#### **--status**=**good** | *better* | *best*
@@ -65,7 +65,7 @@ This is an example of three arguments following an OPTION. If the number of argu
#### **--test**=**test**
-OPTIONS that are followed by an equal sign include an argument after the equal sign in **bold**. If there is a default argument, that is used if the OPTION is not specified in the command, the argument after the eqaul sign is displayed in **bold**. All arguments must be listed and explained in the text below the OPTION.
+OPTIONS that are followed by an equal sign include an argument after the equal sign in **bold**. If there is a default argument, that is used if the OPTION is not specified in the command, the argument after the equal sign is displayed in **bold**. All arguments must be listed and explained in the text below the OPTION.
| Argument | Description |
| ------------------ | --------------------------------------------------------------------------- |
@@ -102,6 +102,7 @@ All EXAMPLES are listed in this section. This section should be at the end of ea
Description of the EXAMPLE
```
+### Example comment
$ podman command
$ podman command -o
@@ -111,9 +112,16 @@ $ cat $HOME/Dockerfile | podman command --option
Description of the EXAMPLE two
```
-$ podman command --redhat
+# podman command --status=better
+```
+## SEE ALSO
+All commands, including commands with OPTIONS, and config-files mentioned in the manpage have to be listed here. Podman commands, including commands with OPTIONS, and config-files have to be linked. If a command is mentioned several times with different OPTIONS it just have to be linked once. All other commands, including commands with OPTIONS, and config-files just have to be mentioned. If a command is mentioned several times with different OPTIONS it just has to be linked once.
-$ podman command --redhat better
+Example:
+**[podman(1)](podman.1.md)**, **[podman-run(1)](podman-run.1.md)**, **[podman-create(1)](podman-create.1.md)**
-$ podman command --redhat=better
-```
+## HISTORY
+Normally, the dates of changes, the content of the changes and the person who provided them is listed here. Most manpages don't keep this record.
+
+Example:\
+December 2021, Originally compiled by Alexander Richter <example@redhat.com>
diff --git a/docs/source/markdown/podman-attach.1.md b/docs/source/markdown/podman-attach.1.md
index 092772916..0a5948b4e 100644
--- a/docs/source/markdown/podman-attach.1.md
+++ b/docs/source/markdown/podman-attach.1.md
@@ -10,7 +10,7 @@ podman\-attach - Attach to a running container
## DESCRIPTION
**podman attach** attaches to a running *container* using the *container's name* or *ID*, to either view its ongoing output or to control it interactively.\
-The *container* can detached from (and leave it running) using a configurable key sequence. The default sequence is `ctrl-p,ctrl-q`. Configure the keys sequence using the **--detach-keys** option, or specifying it in the `containers.conf` file: see **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for more information.
+The *container* can detached from (and leave it running) using a configurable key sequence. The default sequence is `ctrl-p,ctrl-q`. Configure the keys sequence using the **--detach-keys** OPTION, or specifying it in the `containers.conf` file: see **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for more information.
## OPTIONS
#### **--detach-keys**=**sequence**
@@ -18,9 +18,8 @@ The *container* can detached from (and leave it running) using a configurable ke
Specify the key **sequence** for detaching a *container*. Format is a single character `[a-Z]` or one or more `ctrl-<value>` characters where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. Specifying "" will disable this feature. The default is `ctrl-p,ctrl-q`.
#### **--latest**, **-l**
-
-Instead of providing the *container name* or *ID*, use the last created *container*. If you use methods other than Podman to run containers such as CRI-O, the last started *container* could be from either of those methods. The default is **false**.\
-*IMPORTANT: This option is not available with the remote Podman client*
+Instead of providing the *container name* or *ID*, use the last created *container*. If other methods are used than Podman to run containers such as `CRI-O`, the last started *container* could be from either of those methods. The default is **false**.\
+*IMPORTANT: This OPTION is not available with the remote Podman client.*
#### **--no-stdin**
diff --git a/docs/source/markdown/podman-commit.1.md b/docs/source/markdown/podman-commit.1.md
index 92574cdc5..bb7d3ce70 100644
--- a/docs/source/markdown/podman-commit.1.md
+++ b/docs/source/markdown/podman-commit.1.md
@@ -23,7 +23,17 @@ Set the author for the committed image.
#### **--change**, **-c**=*instruction*
Apply the following possible instructions to the created image:
-**CMD** | **ENTRYPOINT** | **ENV** | **EXPOSE** | **LABEL** | **ONBUILD** | **STOPSIGNAL** | **USER** | **VOLUME** | **WORKDIR**
+
+- *CMD*
+- *ENTRYPOINT*
+- *ENV*
+- *EXPOSE*
+- *LABEL*
+- *ONBUILD*
+- *STOPSIGNAL*
+- *USER*
+- *VOLUME*
+- *WORKDIR*
Can be set multiple times.
diff --git a/docs/source/markdown/podman-completion.1.md b/docs/source/markdown/podman-completion.1.md
index 4ebe4e2e1..f8589ce68 100644
--- a/docs/source/markdown/podman-completion.1.md
+++ b/docs/source/markdown/podman-completion.1.md
@@ -4,60 +4,60 @@
podman\-completion - Generate shell completion scripts
## SYNOPSIS
-**podman completion** [*options*] *bash*|*zsh*|*fish*|*powershell*
+**podman completion** [*options*] *bash* | *zsh* | *fish* | *powershell*
## DESCRIPTION
-The completion command generates shell completion scripts for a variety of shells. Supported shells are **bash**, **zsh**, **fish** and **powershell**.
+**podman completion** generates shell completion scripts for a variety of shells. Supported shells are *bash*, *zsh*, *fish* and *powershell*.
-These script are used by the shell to provide suggestions and complete commands when you are typing the command and press [TAB].
+These script are used by the shell to provide suggestions and complete commands when the command is typed and `[TAB]` is pressed.
Usually these scripts are automatically installed via the package manager.
## OPTIONS
-#### **--file**, **-f**
+#### **--file**, **-f**=*file*
-Write the generated output to file.
+Write the generated output to a file.
#### **--no-desc**
-Do not provide description in the completions.
+Do not provide description in the completions. The default is **false**.
## Installation
### BASH
-Make sure you have `bash-completion` installed on the system.
+`bash-completion` has to be installed on the system.
-To load the completion script into the current session run:
-`source <(podman completion bash)`
+To load the completion script into the current session run:\
+**source <(podman completion bash)**.
-To make it available for all bash sessions run:
-`podman completion bash -f /etc/bash_completion.d/podman`
+To make it available for all bash sessions run:\
+**podman completion -f /etc/bash_completion.d/podman bash**.
### ZSH
-If shell completion is not already enabled in the environment you will need to enable it. You can execute the following once:
-`echo "autoload -U compinit; compinit" >> ~/.zshrc`
+Shell completion needs to be already enabled in the environment. The following can be executed:\
+**echo "autoload -U compinit; compinit" >> ~/.zshrc**
-To make it available for all zsh sessions run:
-`podman completion zsh -f "${fpath[1]}/_podman"`
+To make it available for all zsh sessions run:\
+**podman completion -f "${fpath[1]}/_podman zsh"**
-Once you reload the shell the auto-completion should be working.
+Once the shell is reloaded the auto-completion should be working.
### FISH
To load the completion script into the current session run:
-`podman completion fish | source`
+**podman completion fish | source**
To make it available for all fish sessions run:
-`podman completion fish -f ~/.config/fish/completions/podman.fish`
+**podman completion -f ~/.config/fish/completions/podman.fish fish**
### POWERSHELL
To load the completion script into the current session run:
-`podman.exe completion powershell | Out-String | Invoke-Expression`
+**podman.exe completion powershell | Out-String | Invoke-Expression**
To make it available in all powershell sessions that a user has, write the
completion output to a file and source that to the user's powershell profile.
-More information about profiles is available with `Get-Help about_Profiles`.
+More information about profiles is available with **Get-Help about_Profiles**.
## SEE ALSO
-[podman(1)](podman.1.md)
+**[podman(1)](podman.1.md)**, zsh(1), fish(1), powershell(1)
diff --git a/docs/source/markdown/podman-container-checkpoint.1.md b/docs/source/markdown/podman-container-checkpoint.1.md
index 271a44c9d..a86389f59 100644
--- a/docs/source/markdown/podman-container-checkpoint.1.md
+++ b/docs/source/markdown/podman-container-checkpoint.1.md
@@ -4,96 +4,102 @@
podman\-container\-checkpoint - Checkpoints one or more running containers
## SYNOPSIS
-**podman container checkpoint** [*options*] *container* ...
+**podman container checkpoint** [*options*] *container* [*container* ...]
## DESCRIPTION
-Checkpoints all the processes in one or more containers. You may use container IDs or names as input.
+**podman container checkpoint** checkpoints all the processes in one or more *containers*. A *container* can be restored from a checkpoint with **[podman-container-restore](podman-container-restore.1.md)**. The *container IDs* or *names* are used as input.
## OPTIONS
#### **--all**, **-a**
-Checkpoint all running containers.
+Checkpoint all running *containers*. The default is **false**.
-#### **--compress**, **-c**
+#### **--compress**, **-c**=**zstd** | *none* | *gzip*
Specify the compression algorithm used for the checkpoint archive created
-with the **--export, -e** option. Possible algorithms are *gzip*, *none*
-and *zstd*. If no compression algorithm is specified Podman will use
-*zstd*.
+with the **--export, -e** OPTION. Possible algorithms are **zstd**, *none*
+and *gzip*. The default is **zstd**.
One possible reason to use *none* is to enable faster creation of checkpoint
archives. Not compressing the checkpoint archive can result in faster checkpoint
archive creation.
-```
-# podman container checkpoint -l --compress=none --export=dump.tar
-# podman container checkpoint -l --compress=gzip --export=dump.tar.gz
-```
-
-#### **--export**, **-e**
+#### **--export**, **-e**=*archive*
Export the checkpoint to a tar.gz file. The exported checkpoint can be used
-to import the container on another system and thus enabling container live
-migration. This checkpoint archive also includes all changes to the container's
-root file-system, if not explicitly disabled using **--ignore-rootfs**
+to import the *container* on another system and thus enabling container live
+migration. This checkpoint archive also includes all changes to the *container's*
+root file-system, if not explicitly disabled using **--ignore-rootfs**.
#### **--ignore-rootfs**
This only works in combination with **--export, -e**. If a checkpoint is
exported to a tar.gz file it is possible with the help of **--ignore-rootfs**
to explicitly disable including changes to the root file-system into
-the checkpoint archive file.
+the checkpoint archive file. The default is **false**.
#### **--ignore-volumes**
-This option must be used in combination with the **--export, -e** option.
-When this option is specified, the content of volumes associated with
-the container will not be included into the checkpoint tar.gz file.
+This OPTION must be used in combination with the **--export, -e** OPTION.
+When this OPTION is specified, the content of volumes associated with
+the *container* will not be included into the checkpoint tar.gz file. The default is **false**.
#### **--keep**, **-k**
-Keep all temporary log and statistics files created by CRIU during checkpointing. These files
-are not deleted if checkpointing fails for further debugging. If checkpointing succeeds these
-files are theoretically not needed, but if these files are needed Podman can keep the files
-for further analysis.
+Keep all temporary log and statistics files created by CRIU during checkpointing. These files are not deleted if checkpointing fails for further debugging. If checkpointing succeeds these files are theoretically not needed, but if these files are needed Podman can keep the files for further analysis. The default is **false**.
#### **--latest**, **-l**
-Instead of providing the container name or ID, checkpoint the last created container. (This option is not available with the remote Podman client)
+Instead of providing the *container ID* or *name*, use the last created *container*. If you use methods other than Podman to run *containers* such as `CRI-O`, the last started *container* could be from either of those methods. The default is **false**.\
+*IMPORTANT: This OPTION is not available with the remote Podman client.*
#### **--leave-running**, **-R**
-Leave the container running after checkpointing instead of stopping it.
+Leave the *container* running after checkpointing instead of stopping it. The default is **false**.
#### **--pre-checkpoint**, **-P**
-Dump the container's memory information only, leaving the container running. Later
-operations will supersede prior dumps. It only works on runc 1.0-rc3 or higher.
+Dump the *container's* memory information only, leaving the *container* running. Later
+operations will supersede prior dumps. It only works on `runc 1.0-rc3` or `higher`. The default is **false**.
#### **--tcp-established**
-Checkpoint a container with established TCP connections. If the checkpoint
-image contains established TCP connections, this options is required during
-restore. Defaults to not checkpointing containers with established TCP
-connections.
+Checkpoint a *container* with established TCP connections. If the checkpoint
+image contains established TCP connections, this OPTION is required during
+restore. Defaults to not checkpointing *containers* with established TCP
+connections. The default is **false**.
#### **--with-previous**
-Check out the container with previous criu image files in pre-dump. It only works
-without **--pre-checkpoint** or **-P**. It only works on runc 1.0-rc3 or higher.
+Check out the *container* with previous criu image files in pre-dump. It only works on `runc 1.0-rc3` or `higher`. The default is **false**.\
+*IMPORTANT: This OPTION is not available with **--pre-checkpoint***.
+
-## EXAMPLE
+## EXAMPLES
-podman container checkpoint mywebserver
+Make a checkpoint for the container "mywebserver".
+```
+# podman container checkpoint mywebserver
+```
-podman container checkpoint 860a4b23
+Dumps the container's memory information of the latest container into an archive.
+```
+# podman container checkpoint -P -e pre-checkpoint.tar.gz -l
+```
-podman container checkpoint -P -e pre-checkpoint.tar.gz -l
+Keep the container's memory information from an older dump and add the new container's memory information.
+```
+# podman container checkpoint --with-previous -e checkpoint.tar.gz -l
+```
-podman container checkpoint --with-previous -e checkpoint.tar.gz -l
+Dump the container's memory information of the latest container into an archive with the specified compress method.
+```
+# podman container checkpoint -l --compress=none --export=dump.tar
+# podman container checkpoint -l --compress=gzip --export=dump.tar.gz
+```
## SEE ALSO
-podman(1), podman-container-restore(1)
+**[podman(1)](podman.1.md)**, **[podman-container-restore(1)](podman-container-restore.1.md)**
## HISTORY
September 2018, Originally compiled by Adrian Reber <areber@redhat.com>
diff --git a/docs/source/markdown/podman-container-cleanup.1.md b/docs/source/markdown/podman-container-cleanup.1.md
index 19d0b7818..f33b68a1c 100644
--- a/docs/source/markdown/podman-container-cleanup.1.md
+++ b/docs/source/markdown/podman-container-cleanup.1.md
@@ -4,51 +4,51 @@
podman\-container\-cleanup - Cleanup the container's network and mountpoints
## SYNOPSIS
-**podman container cleanup** [*options*] *container*
+**podman container cleanup** [*options*] *container* [*container* ...]
## DESCRIPTION
-**podman container cleanup** cleans up exited containers by removing all mountpoints and network configuration from the host. The container name or ID can be used. The cleanup command does not remove the containers. Running containers will not be cleaned up.
-Sometimes container's mount points and network stacks can remain if the podman command was killed or the container ran in daemon mode. This command is automatically executed when you run containers in daemon mode by the conmon process when the container exits.
+**podman container cleanup** cleans up exited *containers* by removing all mountpoints and network configuration from the host. The *container name* or *ID* can be used. The cleanup command does not remove the *containers*. Running *containers* will not be cleaned up.\
+Sometimes container mount points and network stacks can remain if the podman command was killed or the *container* ran in daemon mode. This command is automatically executed when you run *containers* in daemon mode by the `conmon process` when the *container* exits.
## OPTIONS
#### **--all**, **-a**
-Cleanup all containers.
+Cleanup all *containers*. The default is **false**.
-#### **--exec**=_session_
+#### **--exec**=*session*
-Clean up an exec session for a single container.
-Can only be specified if a single container is being cleaned up (conflicts with **--all** as such).
-If **--rm** is not specified, temporary files for the exec session will be cleaned up; if it is, the exec session will be removed from the container.
-Conflicts with **--rmi** as the container is not being cleaned up so the image cannot be removed.
+Clean up an exec session for a single *container*.
+Can only be specified if a single *container* is being cleaned up (conflicts with **--all** as such). If **--rm** is not specified, temporary files for the exec session will be cleaned up; if it is, the exec session will be removed from the *container*.\
+*IMPORTANT: Conflicts with **--rmi** as the container is not being cleaned up so the image cannot be removed.*
#### **--latest**, **-l**
-Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+
+Instead of providing the *container ID* or *name*, use the last created *container*. If you use methods other than Podman to run *containers* such as `CRI-O`, the last started *container* could be from either of those methods. The default is **false**.\
+*IMPORTANT: This OPTION is not available with the remote Podman client.*
#### **--rm**
-After cleanup, remove the container entirely.
+After cleanup, remove the *container* entirely. The default is **false**.
#### **--rmi**
-After cleanup, remove the image entirely.
-
-## EXAMPLE
-
-`podman container cleanup mywebserver`
-
-`podman container cleanup mywebserver myflaskserver 860a4b23`
+After cleanup, remove the image entirely. The default is **false**.
-`podman container cleanup 860a4b23`
+## EXAMPLES
-`podman container cleanup -a`
+Cleanup the container "mywebserver".
+```
+$ podman container cleanup mywebserver
+```
-`podman container cleanup --latest`
+Cleanup the containers with the names "mywebserver", "myflaskserver", "860a4b23".
+```
+$ podman container cleanup mywebserver myflaskserver 860a4b23
+```
## SEE ALSO
-**podman**(1), **podman-container**(1), **conmon**(8).
+**[podman(1)](podman.1.md)**, **[podman-container(1)](podman-container.1.md)**, conmon(8)
## HISTORY
Jun 2018, Originally compiled by Dan Walsh <dwalsh@redhat.com>
diff --git a/docs/source/markdown/podman-container-exists.1.md b/docs/source/markdown/podman-container-exists.1.md
index 381d968ab..e42489d63 100644
--- a/docs/source/markdown/podman-container-exists.1.md
+++ b/docs/source/markdown/podman-container-exists.1.md
@@ -1,42 +1,40 @@
% podman-container-exists(1)
## NAME
-podman-container-exists - Check if a container exists in local storage
+podman\-container\-exists - Check if a container exists in local storage
## SYNOPSIS
**podman container exists** [*options*] *container*
## DESCRIPTION
-**podman container exists** checks if a container exists in local storage. The **ID** or **Name**
-of the container may be used as input. Podman will return an exit code
-of `0` when the container is found. A `1` will be returned otherwise. An exit code of `125` indicates there
-was an issue accessing the local storage.
+**podman container exists** checks if a container exists in local storage. The *container ID* or *name* is used as input. Podman will return an exit code
+of `0` when the container is found. A `1` will be returned otherwise. An exit code of `125` indicates there was an issue accessing the local storage.
## OPTIONS
-#### **--external**=*true|false*
-Check for external containers as well as Podman containers. These external containers are generally created via other container technology such as Buildah or CRI-O.
+#### **--external**
+Check for external *containers* as well as Podman *containers*. These external *containers* are generally created via other container technology such as `Buildah` or `CRI-O`. The default is **false**.
**-h**, **--help**
-Print usage statement
+Prints usage statement.
## EXAMPLES
-Check if an container called `webclient` exists in local storage (the container does actually exist).
+Check if an container called "webclient" exists in local storage. Here, the container does exist.
```
$ podman container exists webclient
$ echo $?
0
```
-Check if an container called `webbackend` exists in local storage (the container does not actually exist).
+Check if an container called "webbackend" exists in local storage. Here, the container does not exist.
```
$ podman container exists webbackend
$ echo $?
1
```
-Check if an container called `ubi8-working-container` created via Buildah exists in local storage (the container does not actually exist).
+Check if an container called "ubi8-working-container" created via Buildah exists in local storage. Here, the container does not exist.
```
$ podman container exists --external ubi8-working-container
$ echo $?
@@ -44,7 +42,7 @@ $ echo $?
```
## SEE ALSO
-podman(1)
+**[podman(1)](podman.1.md)**
## HISTORY
-November 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)
+November 2018, Originally compiled by Brent Baude <bbaude@redhat.com>
diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md
index 734d00971..2510eaa81 100644
--- a/docs/source/markdown/podman.1.md
+++ b/docs/source/markdown/podman.1.md
@@ -336,9 +336,11 @@ Images are pulled under `XDG_DATA_HOME` when specified, otherwise in the home di
Currently the slirp4netns package is required to be installed to create a network device, otherwise rootless containers need to run in the network namespace of the host.
+In certain environments like HPC (High Performance Computing), users cannot take advantage of the additional UIDs and GIDs from the /etc/subuid and /etc/subgid systems. However, in this environment, rootless Podman can operate with a single UID. To make this work, set the `ignore_chown_errors` option in the /etc/containers/storage.conf or in ~/.config/containers/storage.conf files. This option tells Podman when pulling an image to ignore chown errors when attempting to change a file in a container image to match the non-root UID in the image. This means all files get saved as the user's UID. Note this could cause issues when running the container.
+
### **NOTE:** Unsupported file systems in rootless mode
-The Overlay file system (OverlayFS) is not supported in rootless mode. The fuse-overlayfs package is a tool that provides the functionality of OverlayFS in user namespace that allows mounting file systems in rootless environments. It is recommended to install the fuse-overlayfs package. In rootless mode Podman will automatically use the fuse-overlafs program as the mount_program if installed, as long as the $HOME/.config/containers/storage.conf file was not previously created. If storage.conf exists in the homedir, add `mount_program = "/usr/bin/fuse-overlayfs"` under `[storage.options.overlay]` to enable this feature.
+The Overlay file system (OverlayFS) is not supported with kernels prior to 5.12.9 in rootless mode. The fuse-overlayfs package is a tool that provides the functionality of OverlayFS in user namespace that allows mounting file systems in rootless environments. It is recommended to install the fuse-overlayfs package. In rootless mode, Podman will automatically use the fuse-overlayfs program as the mount_program if installed, as long as the $HOME/.config/containers/storage.conf file was not previously created. If storage.conf exists in the homedir, add `mount_program = "/usr/bin/fuse-overlayfs"` under `[storage.options.overlay]` to enable this feature.
The Network File System (NFS) and other distributed file systems (for example: Lustre, Spectrum Scale, the General Parallel File System (GPFS)) are not supported when running in rootless mode as these file systems do not understand user namespace. However, rootless Podman can make use of an NFS Homedir by modifying the `$HOME/.config/containers/storage.conf` to have the `graphroot` option point to a directory stored on local (Non NFS) storage.
diff --git a/libpod/container_exec.go b/libpod/container_exec.go
index c359f1e5d..737bf74ad 100644
--- a/libpod/container_exec.go
+++ b/libpod/container_exec.go
@@ -1,6 +1,7 @@
package libpod
import (
+ "context"
"io/ioutil"
"net/http"
"os"
@@ -539,18 +540,7 @@ func (c *Container) ExecStop(sessionID string, timeout *uint) error {
var cleanupErr error
// Retrieve exit code and update status
- exitCode, err := c.readExecExitCode(session.ID())
- if err != nil {
- cleanupErr = err
- }
- session.ExitCode = exitCode
- session.PID = 0
- session.State = define.ExecStateStopped
-
- if err := c.save(); err != nil {
- if cleanupErr != nil {
- logrus.Errorf("Error stopping container %s exec session %s: %v", c.ID(), session.ID(), cleanupErr)
- }
+ if err := retrieveAndWriteExecExitCode(c, session.ID()); err != nil {
cleanupErr = err
}
@@ -592,15 +582,7 @@ func (c *Container) ExecCleanup(sessionID string) error {
return errors.Wrapf(define.ErrExecSessionStateInvalid, "cannot clean up container %s exec session %s as it is running", c.ID(), session.ID())
}
- exitCode, err := c.readExecExitCode(session.ID())
- if err != nil {
- return err
- }
- session.ExitCode = exitCode
- session.PID = 0
- session.State = define.ExecStateStopped
-
- if err := c.save(); err != nil {
+ if err := retrieveAndWriteExecExitCode(c, session.ID()); err != nil {
return err
}
}
@@ -637,9 +619,9 @@ func (c *Container) ExecRemove(sessionID string, force bool) error {
return err
}
if !running {
- session.State = define.ExecStateStopped
- // TODO: should we retrieve exit code here?
- // TODO: Might be worth saving state here.
+ if err := retrieveAndWriteExecExitCode(c, session.ID()); err != nil {
+ return err
+ }
}
}
@@ -653,6 +635,10 @@ func (c *Container) ExecRemove(sessionID string, force bool) error {
return err
}
+ if err := retrieveAndWriteExecExitCode(c, session.ID()); err != nil {
+ return err
+ }
+
if err := c.cleanupExecBundle(session.ID()); err != nil {
return err
}
@@ -757,10 +743,25 @@ func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resi
session, err := c.ExecSession(sessionID)
if err != nil {
+ if errors.Cause(err) == define.ErrNoSuchExecSession {
+ // TODO: If a proper Context is ever plumbed in here, we
+ // should use it.
+ // As things stand, though, it's not worth it - this
+ // should always terminate quickly since it's not
+ // streaming.
+ diedEvent, err := c.runtime.GetExecDiedEvent(context.Background(), c.ID(), sessionID)
+ if err != nil {
+ return -1, errors.Wrapf(err, "error retrieving exec session %s exit code", sessionID)
+ }
+ return diedEvent.ContainerExitCode, nil
+ }
return -1, err
}
exitCode := session.ExitCode
if err := c.ExecRemove(sessionID, false); err != nil {
+ if errors.Cause(err) == define.ErrNoSuchExecSession {
+ return exitCode, nil
+ }
return -1, err
}
@@ -927,6 +928,8 @@ func (c *Container) getActiveExecSessions() ([]string, error) {
session.PID = 0
session.State = define.ExecStateStopped
+ c.newExecDiedEvent(session.ID(), exitCode)
+
needSave = true
}
if err := c.cleanupExecBundle(id); err != nil {
@@ -1036,6 +1039,22 @@ func writeExecExitCode(c *Container, sessionID string, exitCode int) error {
return errors.Wrapf(err, "error syncing container %s state to remove exec session %s", c.ID(), sessionID)
}
+ return justWriteExecExitCode(c, sessionID, exitCode)
+}
+
+func retrieveAndWriteExecExitCode(c *Container, sessionID string) error {
+ exitCode, err := c.readExecExitCode(sessionID)
+ if err != nil {
+ return err
+ }
+
+ return justWriteExecExitCode(c, sessionID, exitCode)
+}
+
+func justWriteExecExitCode(c *Container, sessionID string, exitCode int) error {
+ // Write an event first
+ c.newExecDiedEvent(sessionID, exitCode)
+
session, ok := c.state.ExecSessions[sessionID]
if !ok {
// Exec session already removed.
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 69ba4671e..3e4eea003 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -428,7 +428,7 @@ func (c *Container) setupStorage(ctx context.Context) error {
},
LabelOpts: c.config.LabelOpts,
}
- if c.restoreFromCheckpoint {
+ if c.restoreFromCheckpoint && !c.config.Privileged {
// If restoring from a checkpoint, the root file-system
// needs to be mounted with the same SELinux labels as
// it was mounted previously.
diff --git a/libpod/events.go b/libpod/events.go
index 839229674..22c51aeec 100644
--- a/libpod/events.go
+++ b/libpod/events.go
@@ -46,7 +46,22 @@ func (c *Container) newContainerExitedEvent(exitCode int32) {
e.Type = events.Container
e.ContainerExitCode = int(exitCode)
if err := c.runtime.eventer.Write(e); err != nil {
- logrus.Errorf("unable to write pod event: %q", err)
+ logrus.Errorf("unable to write container exited event: %q", err)
+ }
+}
+
+// newExecDiedEvent creates a new event for an exec session's death
+func (c *Container) newExecDiedEvent(sessionID string, exitCode int) {
+ e := events.NewEvent(events.ExecDied)
+ e.ID = c.ID()
+ e.Name = c.Name()
+ e.Image = c.config.RootfsImageName
+ e.Type = events.Container
+ e.ContainerExitCode = exitCode
+ e.Attributes = make(map[string]string)
+ e.Attributes["execID"] = sessionID
+ if err := c.runtime.eventer.Write(e); err != nil {
+ logrus.Errorf("unable to write exec died event: %q", err)
}
}
@@ -154,3 +169,25 @@ func (r *Runtime) GetLastContainerEvent(ctx context.Context, nameOrID string, co
// return the last element in the slice
return containerEvents[len(containerEvents)-1], nil
}
+
+// GetExecDiedEvent takes a container name or ID, exec session ID, and returns
+// that exec session's Died event (if it has already occurred).
+func (r *Runtime) GetExecDiedEvent(ctx context.Context, nameOrID, execSessionID string) (*events.Event, error) {
+ filters := []string{
+ fmt.Sprintf("container=%s", nameOrID),
+ "event=exec_died",
+ "type=container",
+ fmt.Sprintf("label=execID=%s", execSessionID),
+ }
+
+ containerEvents, err := r.GetEvents(ctx, filters)
+ if err != nil {
+ return nil, err
+ }
+ // There *should* only be one event maximum.
+ // But... just in case... let's not blow up if there's more than one.
+ if len(containerEvents) < 1 {
+ return nil, errors.Wrapf(events.ErrEventNotFound, "exec died event for session %s (container %s) not found", execSessionID, nameOrID)
+ }
+ return containerEvents[len(containerEvents)-1], nil
+}
diff --git a/libpod/events/config.go b/libpod/events/config.go
index 085fa9d52..d88d7b6e3 100644
--- a/libpod/events/config.go
+++ b/libpod/events/config.go
@@ -127,6 +127,8 @@ const (
Create Status = "create"
// Exec ...
Exec Status = "exec"
+ // ExecDied indicates that an exec session in a container died.
+ ExecDied Status = "exec_died"
// Exited indicates that a container's process died
Exited Status = "died"
// Export ...
diff --git a/libpod/events/events.go b/libpod/events/events.go
index 01ea6a386..e03215eff 100644
--- a/libpod/events/events.go
+++ b/libpod/events/events.go
@@ -149,6 +149,8 @@ func StringToStatus(name string) (Status, error) {
return Create, nil
case Exec.String():
return Exec, nil
+ case ExecDied.String():
+ return ExecDied, nil
case Exited.String():
return Exited, nil
case Export.String():
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index c928e02a6..5446841f6 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -1090,7 +1090,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro
}
c.newNetworkEvent(events.NetworkDisconnect, netName)
- if c.state.State != define.ContainerStateRunning {
+ if !c.ensureState(define.ContainerStateRunning, define.ContainerStateCreated) {
return nil
}
@@ -1145,7 +1145,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
return err
}
c.newNetworkEvent(events.NetworkConnect, netName)
- if c.state.State != define.ContainerStateRunning {
+ if !c.ensureState(define.ContainerStateRunning, define.ContainerStateCreated) {
return nil
}
if c.state.NetNS == nil {
diff --git a/libpod/options.go b/libpod/options.go
index f942d264b..d3be46ad8 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1641,6 +1641,19 @@ func WithVolumeGID(gid int) VolumeCreateOption {
}
}
+// WithVolumeNoChown prevents the volume from being chowned to the process uid at first use.
+func WithVolumeNoChown() VolumeCreateOption {
+ return func(volume *Volume) error {
+ if volume.valid {
+ return define.ErrVolumeFinalized
+ }
+
+ volume.state.NeedsChown = false
+
+ return nil
+ }
+}
+
// withSetAnon sets a bool notifying libpod that this volume is anonymous and
// should be removed when containers using it are removed and volumes are
// specified for removal.
diff --git a/libpod/volume_internal.go b/libpod/volume_internal.go
index 694cdd149..19008a253 100644
--- a/libpod/volume_internal.go
+++ b/libpod/volume_internal.go
@@ -39,8 +39,23 @@ func (v *Volume) needsMount() bool {
return true
}
- // Local driver with options needs mount
- return len(v.config.Options) > 0
+ // Commit 28138dafcc added the UID and GID options to this map
+ // However we should only mount when options other than uid and gid are set.
+ // see https://github.com/containers/podman/issues/10620
+ index := 0
+ if _, ok := v.config.Options["UID"]; ok {
+ index++
+ }
+ if _, ok := v.config.Options["GID"]; ok {
+ index++
+ }
+ // when uid or gid is set there is also the "o" option
+ // set so we have to ignore this one as well
+ if index > 0 {
+ index++
+ }
+ // Local driver with options other than uid,gid needs mount
+ return len(v.config.Options) > index
}
// update() updates the volume state from the DB.
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index 50423fb96..e933b9811 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -144,8 +144,8 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
if _, found := r.URL.Query()["dockerfile"]; found {
var m = []string{}
if err := json.Unmarshal([]byte(query.Dockerfile), &m); err != nil {
- utils.BadRequest(w, "dockerfile", query.Dockerfile, err)
- return
+ // it's not json, assume just a string
+ m = append(m, query.Dockerfile)
}
containerFiles = m
} else {
@@ -189,8 +189,8 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
var devices = []string{}
if _, found := r.URL.Query()["devices"]; found {
var m = []string{}
- if err := json.Unmarshal([]byte(query.DropCapabilities), &m); err != nil {
- utils.BadRequest(w, "devices", query.DropCapabilities, err)
+ if err := json.Unmarshal([]byte(query.Devices), &m); err != nil {
+ utils.BadRequest(w, "devices", query.Devices, err)
return
}
devices = m
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 4908e72f6..5a953c047 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -595,7 +595,7 @@ func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrID string,
return nil
}
-func makeExecConfig(options entities.ExecOptions) *libpod.ExecConfig {
+func makeExecConfig(options entities.ExecOptions, rt *libpod.Runtime) (*libpod.ExecConfig, error) {
execConfig := new(libpod.ExecConfig)
execConfig.Command = options.Cmd
execConfig.Terminal = options.Tty
@@ -607,7 +607,20 @@ func makeExecConfig(options entities.ExecOptions) *libpod.ExecConfig {
execConfig.PreserveFDs = options.PreserveFDs
execConfig.AttachStdin = options.Interactive
- return execConfig
+ // Make an exit command
+ storageConfig := rt.StorageConfig()
+ runtimeConfig, err := rt.GetConfig()
+ if err != nil {
+ return nil, errors.Wrapf(err, "error retrieving Libpod configuration to build exec exit command")
+ }
+ // TODO: Add some ability to toggle syslog
+ exitCommandArgs, err := generate.CreateExitCommandArgs(storageConfig, runtimeConfig, false, true, true)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error constructing exit command for exec session")
+ }
+ execConfig.ExitCommand = exitCommandArgs
+
+ return execConfig, nil
}
func checkExecPreserveFDs(options entities.ExecOptions) error {
@@ -647,7 +660,10 @@ func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrID string, o
}
ctr := ctrs[0]
- execConfig := makeExecConfig(options)
+ execConfig, err := makeExecConfig(options, ic.Libpod)
+ if err != nil {
+ return ec, err
+ }
ec, err = terminal.ExecAttachCtr(ctx, ctr, execConfig, &streams)
return define.TranslateExecErrorToExitCode(ec, err), err
@@ -664,20 +680,10 @@ func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrID s
}
ctr := ctrs[0]
- execConfig := makeExecConfig(options)
-
- // Make an exit command
- storageConfig := ic.Libpod.StorageConfig()
- runtimeConfig, err := ic.Libpod.GetConfig()
- if err != nil {
- return "", errors.Wrapf(err, "error retrieving Libpod configuration to build exec exit command")
- }
- // TODO: Add some ability to toggle syslog
- exitCommandArgs, err := generate.CreateExitCommandArgs(storageConfig, runtimeConfig, false, true, true)
+ execConfig, err := makeExecConfig(options, ic.Libpod)
if err != nil {
- return "", errors.Wrapf(err, "error constructing exit command for exec session")
+ return "", err
}
- execConfig.ExitCommand = exitCommandArgs
// Create and start the exec session
id, err := ctr.ExecCreate(execConfig)
diff --git a/pkg/domain/infra/abi/parse/parse.go b/pkg/domain/infra/abi/parse/parse.go
index 1c590d2d6..56c747711 100644
--- a/pkg/domain/infra/abi/parse/parse.go
+++ b/pkg/domain/infra/abi/parse/parse.go
@@ -37,7 +37,7 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error)
return nil, errors.Wrapf(err, "cannot convert UID %s to integer", splitO[1])
}
logrus.Debugf("Removing uid= from options and adding WithVolumeUID for UID %d", intUID)
- libpodOptions = append(libpodOptions, libpod.WithVolumeUID(intUID))
+ libpodOptions = append(libpodOptions, libpod.WithVolumeUID(intUID), libpod.WithVolumeNoChown())
finalVal = append(finalVal, o)
// set option "UID": "$uid"
volumeOptions["UID"] = splitO[1]
@@ -50,7 +50,7 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error)
return nil, errors.Wrapf(err, "cannot convert GID %s to integer", splitO[1])
}
logrus.Debugf("Removing gid= from options and adding WithVolumeGID for GID %d", intGID)
- libpodOptions = append(libpodOptions, libpod.WithVolumeGID(intGID))
+ libpodOptions = append(libpodOptions, libpod.WithVolumeGID(intGID), libpod.WithVolumeNoChown())
finalVal = append(finalVal, o)
// set option "GID": "$gid"
volumeOptions["GID"] = splitO[1]
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at
index 037a4c01f..9e464dbc7 100644
--- a/test/apiv2/10-images.at
+++ b/test/apiv2/10-images.at
@@ -147,4 +147,39 @@ t GET "images/get?names=alpine&names=busybox" 200 '[POSIX tar archive]'
img_cnt=$(tar xf "$WORKDIR/curl.result.out" manifest.json -O | jq "length")
is "$img_cnt" 2 "number of images in tar archive"
+# check build works when uploading container file as a tar, see issue #10660
+TMPD=$(mktemp -d podman-apiv2-test.build.XXXXXXXX)
+function cleanBuildTest() {
+ podman rmi -a -f
+ rm -rf "${TMPD}" &> /dev/null
+}
+CONTAINERFILE_TAR="${TMPD}/containerfile.tar"
+cat > $TMPD/containerfile << EOF
+FROM quay.io/libpod/alpine_labels:latest
+EOF
+tar --format=posix -C $TMPD -cvf ${CONTAINERFILE_TAR} containerfile &> /dev/null
+
+curl -XPOST --data-binary @<(cat $CONTAINERFILE_TAR) \
+ -H "content-type: application/x-tar" \
+ --dump-header "${TMPD}/headers.txt" \
+ -o "${TMPD}/response.txt" \
+ "http://$HOST:$PORT/v1.40/libpod/build?dockerfile=containerfile" &> /dev/null
+
+BUILD_TEST_ERROR=""
+
+if ! grep -q '200 OK' "${TMPD}/headers.txt"; then
+ echo -e "${red}NOK: Image build from tar failed response was not 200 OK"
+ BUILD_TEST_ERROR="1"
+fi
+
+if ! grep -q 'quay.io/libpod/alpine_labels' "${TMPD}/response.txt"; then
+ echo -e "${red}NOK: Image build from tar failed image name not in response"
+ BUILD_TEST_ERROR="1"
+fi
+
+cleanBuildTest
+if [[ "${BUILD_TEST_ERROR}" ]]; then
+ exit 1
+fi
+
# vim: filetype=sh
diff --git a/test/compose/test-compose b/test/compose/test-compose
index 981f78a79..70db6dd55 100755
--- a/test/compose/test-compose
+++ b/test/compose/test-compose
@@ -183,6 +183,8 @@ function test_port() {
fi
echo "# cat $WORKDIR/server.log:"
cat $WORKDIR/server.log
+ echo "# cat $logfile:"
+ cat $logfile
return
fi
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index 6255690b1..abaacdd5e 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -604,4 +604,38 @@ RUN echo hello`, ALPINE)
Expect(inspect.OutputToString()).To(Equal("windows"))
})
+
+ It("podman build device test", func() {
+ if _, err := os.Lstat("/dev/fuse"); err != nil {
+ Skip(fmt.Sprintf("test requires stat /dev/fuse to work: %v", err))
+ }
+ containerfile := fmt.Sprintf(`FROM %s
+RUN ls /dev/fuse`, ALPINE)
+ containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile")
+ err := ioutil.WriteFile(containerfilePath, []byte(containerfile), 0755)
+ Expect(err).To(BeNil())
+ session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--file", containerfilePath, podmanTest.TempDir})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(125))
+
+ session = podmanTest.Podman([]string{"build", "--pull-never", "--device", "/dev/fuse", "-t", "test", "--file", containerfilePath, podmanTest.TempDir})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+
+ It("podman build device rename test", func() {
+ SkipIfRootless("rootless builds do not currently support renaming devices")
+ containerfile := fmt.Sprintf(`FROM %s
+RUN ls /dev/test1`, ALPINE)
+ containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile")
+ err := ioutil.WriteFile(containerfilePath, []byte(containerfile), 0755)
+ Expect(err).To(BeNil())
+ session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--file", containerfilePath, podmanTest.TempDir})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(125))
+
+ session = podmanTest.Podman([]string{"build", "--pull-never", "--device", "/dev/zero:/dev/test1", "-t", "test", "--file", containerfilePath, podmanTest.TempDir})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
})
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 9b77aaef8..4be1b2009 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -668,4 +668,36 @@ USER testuser`, fedoraMinimal)
Expect(strings.Contains(test2.OutputToString(), testString)).To(BeTrue())
})
+
+ It("podman volume with uid and gid works", func() {
+ volName := "testVol"
+ volCreate := podmanTest.Podman([]string{"volume", "create", "--opt", "o=uid=1000", volName})
+ volCreate.WaitWithDefaultTimeout()
+ Expect(volCreate.ExitCode()).To(Equal(0))
+
+ volMount := podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/test", volName), ALPINE, "stat", "-c", "%u", "/test"})
+ volMount.WaitWithDefaultTimeout()
+ Expect(volMount.ExitCode()).To(Equal(0))
+ Expect(volMount.OutputToString()).To(Equal("1000"))
+
+ volName = "testVol2"
+ volCreate = podmanTest.Podman([]string{"volume", "create", "--opt", "o=gid=1000", volName})
+ volCreate.WaitWithDefaultTimeout()
+ Expect(volCreate.ExitCode()).To(Equal(0))
+
+ volMount = podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/test", volName), ALPINE, "stat", "-c", "%g", "/test"})
+ volMount.WaitWithDefaultTimeout()
+ Expect(volMount.ExitCode()).To(Equal(0))
+ Expect(volMount.OutputToString()).To(Equal("1000"))
+
+ volName = "testVol3"
+ volCreate = podmanTest.Podman([]string{"volume", "create", "--opt", "o=uid=1000,gid=1000", volName})
+ volCreate.WaitWithDefaultTimeout()
+ Expect(volCreate.ExitCode()).To(Equal(0))
+
+ volMount = podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/test", volName), ALPINE, "stat", "-c", "%u:%g", "/test"})
+ volMount.WaitWithDefaultTimeout()
+ Expect(volMount.ExitCode()).To(Equal(0))
+ Expect(volMount.OutputToString()).To(Equal("1000:1000"))
+ })
})