mirror of
https://github.com/mviereck/x11docker.git
synced 2021-09-19 22:38:46 +03:00
use python to parse json output of inspect.
This commit is contained in:
@@ -10,6 +10,7 @@ Project website: https://github.com/mviereck/x11docker
|
||||
### Changed
|
||||
- `--backend=nerdctl`: Disallow `--home` in rootless mode.
|
||||
- `--backend`: Allow `--share` in all rootless modes.
|
||||
- Use `python` to parse json output of `inspect`.
|
||||
### Fixed
|
||||
- `--interactive`: Fix output redirection.
|
||||
[(#364)](https://github.com/mviereck/x11docker/issues/364)
|
||||
|
||||
14
README.md
14
README.md
@@ -260,14 +260,14 @@ and [nerdctl](https://github.com/containerd/nerdctl) with option `--backend=BACK
|
||||
- Test status:
|
||||
- x11docker was devolped with rootful `docker`, this is well tested.
|
||||
- Basically tested is `podman`, rootless and rootful.
|
||||
- Barely tested are rootless `docker` and `nerdctl` in rootless and rootful mode.
|
||||
- Barely tested:
|
||||
- rootless `docker`
|
||||
- `nerdctl` in rootless and rootful mode.
|
||||
- Some fixes and adjustments for the less tested setups can be expected.
|
||||
- For rootless mode `podman` is recommended.
|
||||
- Only `podman` allows option `--home` in rootless mode yet.
|
||||
- Only `podman` provides useful file ownerships with option `--share` in rootless mode yet.
|
||||
- For rootful mode `docker` or `podman` are recommended.
|
||||
- `nerdctl` has some limitations because it supports only a subset of `docker` cli options yet.
|
||||
- To allow most of x11docker options with `nerdctl` please provide a container command additional to the image name.
|
||||
- To switch between rootless or rootful mode of `podman` and `nerdctl` just use (or leave) `sudo` or set (or leave) option `--pw`.
|
||||
- For [rootless docker](https://docs.docker.com/engine/security/rootless/) set environment variable `DOCKER_HOST` accordingly.
|
||||
|
||||
@@ -363,10 +363,10 @@ As root you can install, update and remove x11docker in system directories to be
|
||||
- Note: This does not remove `~/.local/share/x11docker` where it stores persistent files of option `--home`.
|
||||
|
||||
What the installation does (just for information):
|
||||
- Copies `x11docker` and `x11docker-gui` to `/usr/bin`.
|
||||
- Creates an icon in `/usr/share/icons`.
|
||||
- Creates `x11docker.desktop` in `/usr/share/applications`.
|
||||
- Copies `README.md`, `CHANGELOG.md` and `LICENSE.txt` to `/usr/share/doc/x11docker`.
|
||||
- Copies scripts `x11docker` and `x11docker-gui` to `/usr/bin`.
|
||||
- Copies icon `x11docker.png` to `/usr/share/icons`.
|
||||
- Creates menu entry `x11docker.desktop` in `/usr/share/applications`.
|
||||
- Copies documentation `README.md`, `CHANGELOG.md` and `LICENSE.txt` to `/usr/share/doc/x11docker`.
|
||||
|
||||
### Shortest way for first installation:
|
||||
- For systems using `sudo`:
|
||||
|
||||
1
TODO.md
1
TODO.md
@@ -5,6 +5,7 @@ x11docker ToDo notes
|
||||
- check `--init=` in all backends rootful and rootless.
|
||||
- `--user`: Check in all rootless modes, maybe disallow except for `--user=root`.
|
||||
- `--user=root --home` in rootless docker and nerdctl: Set up HOME in host user ~/x11docker.
|
||||
- `--backend=podman` rootless: disallow `--home` for different `--user`.
|
||||
- `--init=systemd`: cgroupv2 support #349
|
||||
- replace word 'docker' in messages, variable names and documentation to generalize for podman and nerdctl, too.
|
||||
- check, maybe drop container wm using `x11docker/openbox`. Currently likely fails with different backends.
|
||||
|
||||
167
x11docker
167
x11docker
@@ -11,7 +11,7 @@
|
||||
# Run 'x11docker --help' or scroll down to read usage information.
|
||||
# More documentation at: https://github.com/mviereck/x11docker
|
||||
|
||||
Version="6.9.1-beta-1"
|
||||
Version="6.9.1-beta-2"
|
||||
|
||||
# --enforce-i: Enforce running in interactive mode to allow commands tty and weston-launch in special setups.
|
||||
grep -q -- "--enforce-i" <<< "$*" && case $- in
|
||||
@@ -831,7 +831,7 @@ $(for Line in $Watchpidlist; do pspid "$Line" || echo "(pid $Line not found)" ;
|
||||
done
|
||||
# Container PID not watchable in MSYS2/Cygwin/WSL11.
|
||||
[ "$Containername" ] && {
|
||||
[ "$($Containerbackendbin inspect -f {{.State.Running}} $Containername)" == "true" ] || {
|
||||
$Containerbackendbin inspect $Containername >/dev/null || {
|
||||
debugnote "watchpidlist(): Container $Containername has terminated"
|
||||
saygoodbye "watchpidlist $Containername"
|
||||
}
|
||||
@@ -920,6 +920,62 @@ makecookie() { # bake a cookie
|
||||
mysleep() { # catch cases where sleep only supports integer
|
||||
sleep "${1:-1}" 2>/dev/null || sleep 1
|
||||
}
|
||||
parse_inspect() { # parse json of inspect output using python
|
||||
# parse for keys in output of docker|podman|nerdctl inspect.
|
||||
# Uses python json parser.
|
||||
# $1 String containg inspect output
|
||||
# $2...$n Key. For second level keys provide e.g. "jsonstring" "Config" "Cmd"
|
||||
|
||||
local Parserscript
|
||||
|
||||
Parserscript="$Cachefolder/parse_inspect.py"
|
||||
Parserscript="$(cat << EOF
|
||||
#! /usr/bin/env python
|
||||
import json,sys
|
||||
|
||||
def parse_inspect(*args):
|
||||
"""
|
||||
parse output of docker|podman|nerdctl inspect
|
||||
args:
|
||||
0: ignored
|
||||
1: string containing inspect output
|
||||
2..n: json keys. For second level keys provide e.g. "Config","Cmd"
|
||||
Prints key value as a string.
|
||||
Prints empty string if key not found.
|
||||
A list is printed as a string with '' around each element.
|
||||
"""
|
||||
|
||||
output=""
|
||||
inspect=args[1]
|
||||
inspect=inspect.strip()
|
||||
if inspect[0] == "[" :
|
||||
inspect=inspect[1:-2] # remove enclosing [ ]
|
||||
|
||||
obj=json.loads(inspect)
|
||||
|
||||
for arg in args[2:]: # recursivly find the desired object. Command.Cmd is found with args "Command" , "Cmd"
|
||||
try:
|
||||
obj=obj[arg]
|
||||
except:
|
||||
obj=""
|
||||
|
||||
objtype=str(type(obj))
|
||||
if objtype == "<type 'list'>":
|
||||
for i in obj:
|
||||
output=output+"'"+str(i)+"' "
|
||||
else:
|
||||
output=str(obj)
|
||||
|
||||
if output == "None":
|
||||
output=""
|
||||
|
||||
print(output)
|
||||
|
||||
parse_inspect(*sys.argv)
|
||||
EOF
|
||||
)"
|
||||
echo "$Parserscript" | python - "$@"
|
||||
}
|
||||
storeinfo() { # store some information for later use
|
||||
# store and provide pieces of information
|
||||
# replace entry if codeword is already present
|
||||
@@ -1229,7 +1285,7 @@ writeaccess() { # check if useruid $1 has write access to folder
|
||||
cleanup() { # --cleanup : check for non-removed containers and left cache files
|
||||
# Cleanes x11docker cache and removes running and stopped x11docker containers.
|
||||
# Does not change --home folders.
|
||||
local Orphanedcontainers= Orphanedfolders= Line=
|
||||
local Orphanedcontainers= Orphanedfolders= Line= Inspect Containerid
|
||||
|
||||
note "x11docker will check for orphaned containers from earlier sessions.
|
||||
This can happen if docker was not closed successfully.
|
||||
@@ -1241,20 +1297,20 @@ cleanup() { # --cleanup : check for non-removed containers a
|
||||
grep -q .cache/x11docker <<<$Cachebasefolder && Orphanedfolders="$(find "$Cachebasefolder" -mindepth 1 -maxdepth 1 -type d | sed s%$Cachebasefolder/%% | grep -w -v x11docker-gui)"
|
||||
# e X11DOCKER_LASTCLEANFOLDER may be set by x11docker-gui to spare its cache folder.
|
||||
[ "${X11DOCKER_LASTCLEANFOLDER:-}" ] && Orphanedfolders="$(echo "$Orphanedfolders" | grep -v $X11DOCKER_LASTCLEANFOLDER)"
|
||||
Orphanedcontainers="$($Containerbackendbin ps -a --filter name=x11docker_X | grep -v NAMES | rev | cut -d' ' -f1 | rev)"
|
||||
Orphanedcontainers="$($Containerbackendbin ps -a | grep x11docker_X | rev | cut -d' ' -f1 | rev)"
|
||||
Orphanedcontainers="$Orphanedcontainers $(find "$Cachebasefolder" -mindepth 2 -maxdepth 2 -type f -name 'container.id' -exec cat {} \;)"
|
||||
Orphanedcontainers="$(env IFS='' echo $Orphanedcontainers)"
|
||||
|
||||
# check for double entrys name/id, check for already non-existing containers
|
||||
for Line in $Orphanedcontainers; do
|
||||
$Containerbackendbin inspect $Line -f '{{.Id}}' >/dev/null 2>/dev/null && {
|
||||
echo $Line | grep -q x11docker_X && {
|
||||
$Containerbackendbin inspect $Line -f '{{.Id}}'
|
||||
Line="$($Containerbackendbin inspect $Line -f '{{.Id}}')"
|
||||
Orphanedcontainers="$(sed s/$Line// <<< $Orphanedcontainers)"
|
||||
} ||:
|
||||
Inspect="$($Containerbackendbin inspect $Line 2>/dev/null)"
|
||||
[ -n "$Inspect" ] && {
|
||||
Containerid="$(parse_inspect "$Inspect" "Id")"
|
||||
Orphanedcontainers="$(sed "s%$Line%$Containerid%" <<< "$Orphanedcontainers")"
|
||||
:
|
||||
} || Orphanedcontainers="$(sed s/$Line// <<< $Orphanedcontainers)"
|
||||
done
|
||||
Orphanedcontainers="$(sort <<< "$Orphanedcontainers" | uniq)"
|
||||
|
||||
[ -z "$Orphanedcontainers$Orphanedfolders" ] && {
|
||||
note "No orphaned containers or cache files found. good luck!"
|
||||
@@ -5593,6 +5649,7 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
|
||||
declare -f checkpid
|
||||
declare -f escapestring
|
||||
declare -f mysleep
|
||||
declare -f parse_inspect
|
||||
declare -f pspid
|
||||
declare -f rmcr
|
||||
declare -f rocknroll
|
||||
@@ -5609,6 +5666,7 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
|
||||
echo ""
|
||||
}
|
||||
|
||||
echo "Cachefolder='$Cachefolder'"
|
||||
echo "Containercommand=\"$Containercommand\""
|
||||
echo "Imagename=\"$Imagename\""
|
||||
echo "Messagefile='$Messagefifo'"
|
||||
@@ -5717,7 +5775,6 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
|
||||
ask)
|
||||
[ "$Runsinterminal" = "yes" ] && {
|
||||
echo "grep -x -q '$Imagename' < $Dockerimagelistfile || grep -x -q '$Imagename:latest' < $Dockerimagelistfile || {"
|
||||
# echo " $Containerbackendbin inspect $Imagename >>$Containerlogfile 2>&1 || {"
|
||||
echo " $Containerbackendbin images | grep -q '^$Imagename ' || {"
|
||||
echo " echo 'Image $Imagename not found locally.' >&2"
|
||||
echo " echo 'Do you want to pull it from docker hub?' >&2"
|
||||
@@ -5748,19 +5805,16 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
|
||||
case "$Inspectimage" in
|
||||
no) ;;
|
||||
yes)
|
||||
echo "Inspect=\"\$($Containerbackendbin inspect $Imagename --format='{{.Config.User}}|{{.Config.WorkingDir}}|{{.Architecture}}')\""
|
||||
echo ""
|
||||
echo "Inspect=\"\$($Containerbackendbin inspect $Imagename)\""
|
||||
|
||||
echo "# Check architecture"
|
||||
echo "Containerarchitecture=\"\$(cut -d'|' -f3 <<< \"\$Inspect\")\""
|
||||
echo 'Containerarchitecture=$(parse_inspect "$Inspect" "Architecture")'
|
||||
echo "debugnote \"dockerrc: Image architecture: \$Containerarchitecture\""
|
||||
|
||||
echo "# Check CMD"
|
||||
echo "[ -z \"\$Containercommand\" ] && {"
|
||||
echo " # extract image command from image if not given on cli"
|
||||
echo " Containercommand=\"\$($Containerbackendbin inspect $Imagename --format='{{.Config.Cmd}}')\""
|
||||
echo " Containercommand=\"\${Containercommand#[}\""
|
||||
echo " Containercommand=\"\${Containercommand%]}\""
|
||||
echo ' Containercommand="$(parse_inspect "$Inspect" "Config" "Cmd")"'
|
||||
echo " debugnote \"dockerrc: Image CMD: \$Containercommand\""
|
||||
echo " echo \"\$Containercommand\" | grep -q $(convertpath share $Containerrc) && error 'Recursion error: Found CMD $(convertpath share $Containerrc) in image.
|
||||
Did you use 'docker commit' with an x11docker container?
|
||||
@@ -5771,7 +5825,7 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
|
||||
|
||||
|
||||
echo "# Check USER"
|
||||
echo "Imageuser=\"\$(cut -d'|' -f1 <<< \"\$Inspect\")\""
|
||||
echo 'Imageuser="$(parse_inspect "$Inspect" "Config" "User")"'
|
||||
echo "debugnote \"dockerrc: Image USER: \$Imageuser\""
|
||||
case $Createcontaineruser in
|
||||
yes)
|
||||
@@ -5790,9 +5844,7 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
|
||||
yes) echo "Entrypoint=" ;;
|
||||
no)
|
||||
echo "# Check ENTRYPOINT"
|
||||
echo "Entrypoint=\"\$($Containerbackendbin inspect $Imagename --format='{{.Config.Entrypoint}}')\""
|
||||
echo "Entrypoint=\"\${Entrypoint#[}\""
|
||||
echo "Entrypoint=\"\${Entrypoint%]}\""
|
||||
echo 'Entrypoint="$(parse_inspect "$Inspect" "Config" "Entrypoint")"'
|
||||
echo "debugnote \"dockerrc: Image ENTRYPOINT: \$Entrypoint\""
|
||||
case $Initsystem in
|
||||
systemd|sysvinit|runit|openrc|tini)
|
||||
@@ -5826,7 +5878,7 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
|
||||
|
||||
[ -z "$Workdir" ] && {
|
||||
echo "# Check WORKDIR"
|
||||
echo "Workdir=\"\$(cut -d'|' -f2 <<< \"\$Inspect\")\""
|
||||
echo 'Workdir="$(parse_inspect "$Inspect" "Config" "Workdir")"'
|
||||
echo "debugnote \"dockerrc: Image WORKDIR: \$Workdir\""
|
||||
echo "[ \"\$Workdir\" ] && note \"Found 'WORKDIR \$Workdir' in image.
|
||||
You can change it with option --workdir=DIR.\""
|
||||
@@ -6121,7 +6173,7 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
|
||||
echo "rocknroll || exit 64"
|
||||
echo ""
|
||||
|
||||
[ "$Windowmanagermode" = "none" ] || { ### FIXME: check with podman and nerdctl. Or drop at all?
|
||||
[ "$Windowmanagermode" = "none" ] || { ### FIXME: drop at all?
|
||||
echo "# run window manager (in image or from host)"
|
||||
echo "Windowmanagermode=\"$Windowmanagermode\""
|
||||
echo "Windowmanagercommand=\"$Windowmanagercommand\""
|
||||
@@ -6137,7 +6189,8 @@ $Wmdockercommand"'
|
||||
echo ' [ "$Wmcontainerid" ] && {'
|
||||
echo ' debugnote "dockerrc: Window manager container: $Wmcontainerid"'
|
||||
echo " for ((Count=1 ; Count<=10 ; Count++)); do"
|
||||
echo " Pid1pid=\"\$($Containerbackendbin inspect --format '{{.State.Pid}}' \$Wmcontainerid 2>>$Containerlogfile | rmcr)\""
|
||||
echo " Inspect=\"\$($Containerbackendbin inspect \$Wmcontainerid 2>>$Containerlogfile | rmcr)\""
|
||||
echo ' Pid1pid="$(parse_inspect "$Inspect" "State" "Pid")"'
|
||||
echo " debugnote \"dockerrc: Window manager container: \$Count. check for PID 1: \$Pid1pid\""
|
||||
case $Mobyvm in
|
||||
no) echo ' checkpid "$Pid1pid" && break' ;;
|
||||
@@ -6221,15 +6274,8 @@ $Wmdockercommand"'
|
||||
|
||||
echo "# Wait for pid 1 in container"
|
||||
echo "for ((Count=1 ; Count<=40 ; Count++)); do"
|
||||
case $Containerbackend in
|
||||
nerdctl)
|
||||
echo " Pid1pid=\"\$($Containerbackendbin inspect $Containername 2>>$Containerlogfile | rmcr)\""
|
||||
echo ' Pid1pid="$(grep "\"Pid\"" <<< "$Pid1pid" | tr -dc "0-9")"'
|
||||
;;
|
||||
*)
|
||||
echo " Pid1pid=\"\$($Containerbackendbin inspect --format '{{.State.Pid}}' $Containername 2>>$Containerlogfile | rmcr)\""
|
||||
;;
|
||||
esac
|
||||
echo " Inspect=\"\$($Containerbackendbin inspect $Containername 2>>$Containerlogfile | rmcr)\""
|
||||
echo ' Pid1pid="$(parse_inspect "$Inspect" "State" "Pid")"'
|
||||
echo " debugnote \"dockerrc: \$Count. check for PID 1: \$Pid1pid\""
|
||||
case $Mobyvm in
|
||||
no) echo ' checkpid "$Pid1pid" && break' ;;
|
||||
@@ -6253,15 +6299,7 @@ $(rmcr < '$Containerlogfile' | uniq )"'
|
||||
echo ""
|
||||
|
||||
echo "# Get IP of container"
|
||||
case "$Containerbackend" in
|
||||
nerdctl)
|
||||
echo "Containerip=\"\$($Containerbackendbin inspect $Containername 2>>$Containerlogfile)\""
|
||||
echo 'Containerip="$(grep IPAddress <<< "$Containerip" | head -n1 | tr -cd "[.0-9]")"'
|
||||
;;
|
||||
*)
|
||||
echo "Containerip=\"\$($Containerbackendbin inspect --format '{{ .NetworkSettings.IPAddress }}' $Containername 2>>$Containerlogfile)\""
|
||||
;;
|
||||
esac
|
||||
echo 'Containerip="$(parse_inspect "$Inspect" "NetworkSettings" "IPAddress")"'
|
||||
echo 'storeinfo containerip=$Containerip'
|
||||
echo ""
|
||||
|
||||
@@ -6648,7 +6686,6 @@ check_host() { # check host environment
|
||||
*)
|
||||
#Hostip="$(hostname -I | cut -d' ' -f1)"
|
||||
[ "$Hostip" ] || Hostip="$(ip -4 -o a | grep 'docker0' | awk '{print $4}' | cut -d/ -f1 | grep "172.17.0.1" ||: )"
|
||||
#[ "$Hostip" ] || Hostip="$($Containerbackendbin network inspect bridge --format='{{.IPAM.Config}}' 2>/dev/null | awk '{print $2}')"
|
||||
[ "$Hostip" ] || Hostip="$(ip -4 -o a | grep 'docker0' | awk '{print $4}' | cut -d/ -f1 | head -n1)"
|
||||
[ "$Hostip" ] || Hostip="$(ip -4 -o a | awk '{print $4}' | cut -d/ -f1 | grep "^192\.168\.*" | head -n1)"
|
||||
[ "$Hostip" ] || Hostip="$(ip -4 -o a | awk '{print $4}' | cut -d/ -f1 | grep -v "127.0.0.1" | head -n1)"
|
||||
@@ -7137,7 +7174,17 @@ check_option_interferences() { # check multiple option interferences, change se
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
command -v python >/dev/null || {
|
||||
[ "$Containersetup" = "yes" ] && {
|
||||
note "x11docker needs 'python' to parse output of '$Containerbackend inspect'.
|
||||
This is needed to check ENTRYPOINT and CMD that in turn is needed to set up
|
||||
some x11docker features. To allow more features, please install 'python'
|
||||
or provide a container command to execute.
|
||||
Fallback: Enabling option --no-setup."
|
||||
Containersetup="no"
|
||||
}
|
||||
}
|
||||
|
||||
# --cap-default
|
||||
[ "$Capdropall" = "no" ] && {
|
||||
warning "Option --cap-default disables security hardening
|
||||
@@ -7591,35 +7638,15 @@ check_option_interferences() { # check multiple option interferences, change se
|
||||
nerdctl)
|
||||
note "Option --backend=nerdctl: nerdctl only supports a subset
|
||||
of docker options. That limits support of x11docker features."
|
||||
Inspectimage="no"
|
||||
case "$Containercommand" in
|
||||
"")
|
||||
[ "$Containersetup" = "yes" ] && {
|
||||
note "Option --backend=nerdctl: nerdctl does not support 'inspect'
|
||||
for images that is needed to check ENTRYPOINT and CMD
|
||||
that in turn is needed to set up some x11docker features.
|
||||
To allow more features, please provide a container command to execute.
|
||||
Fallback: Enabling option --no-setup."
|
||||
Containersetup="no"
|
||||
}
|
||||
;;
|
||||
*)
|
||||
Switchcontaineruser="yes"
|
||||
[ "$Capdropall" = "yes" ] && note "Option --backend=nerdctl: x11docker
|
||||
Switchcontaineruser="yes"
|
||||
[ "$Capdropall" = "yes" ] && warning "Option --backend=nerdctl: x11docker
|
||||
will allow some user switching capabilities that would be dropped with
|
||||
other backends. (Because 'nerdctl --exec' does not support option --user.)"
|
||||
[ "$Noentrypoint" = "yes" ] || {
|
||||
note "Option --backend=nerdctl: nerdctl does not support 'inspect'
|
||||
for images that is needed to check ENTRYPOINT and CMD
|
||||
that in turn is needed to set up some x11docker features.
|
||||
Fallback: Disabling ENTRYPOINT with option --no-entrypoint."
|
||||
Noentrypoint="yes"
|
||||
}
|
||||
;;
|
||||
esac
|
||||
other backends. (Because 'nerdctl --exec' does not support option --user.)
|
||||
Though, these are still within nerdctl default capabilities."
|
||||
;;
|
||||
*) note "Option --backend=$Containerbackend: Unknown backend. Will try anyway.
|
||||
You might need option --no-setup." ;;
|
||||
You might need option --no-setup.
|
||||
Known backends are docker, podman and nerdctl." ;;
|
||||
esac
|
||||
|
||||
# Docker installed in Ubuntu snap
|
||||
|
||||
Reference in New Issue
Block a user