From e65a286a6fead54f03d3357da3092622f819edd8 Mon Sep 17 00:00:00 2001 From: XV25 Date: Tue, 4 Feb 2025 14:41:10 +0100 Subject: [PATCH 01/21] Add 2 news options --- cmd/root.go | 2 ++ cmd/run.go | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/cmd/root.go b/cmd/root.go index 981203f..f41f3e5 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -120,6 +120,8 @@ var ( noCacherPtr bool workDirPtr string contNamePtr string + othPtr string + devAccPtr string logger = log.New(os.Stdout, appname+": ", log.Lmsgprefix) dockerRunArgs = []string{ "--interactive", diff --git a/cmd/run.go b/cmd/run.go index 77a856d..8b30755 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -708,6 +708,16 @@ Examples: "--volume=/dev/bus/usb:/dev/bus/usb") dockerRunArgs = append(dockerRunArgs, "--device-cgroup-rule=c 189:* rmw") + + // add commands to include specific usb devices (as stated by https://stackoverflow.com/a/62758958) + if devAccPtr != "" { + var indexes = strings.Split(devAccPtr, ";") + for i := 0; i < len(indexes); i++ { + var s = "--device-cgroup-rule=c " + indexes[i] + ":* rmw" + dockerRunArgs = append(dockerRunArgs, s) + } + } + } if !noUserPtr && userObj.Uid == "0" { @@ -759,6 +769,11 @@ Examples: entrypoint = merge([]string{"bash", createUserScriptPath}, execCommand) } + if othPtr != "" { + // add final custom commands. + dockerRunArgs = append(dockerRunArgs, othPtr) + } + dockerRunArgs = append(dockerRunArgs, imageName) // run command end // ******************************************************** @@ -813,4 +828,7 @@ func init() { runCmd.Flags().BoolVar(&noRMPtr, "no-rm", false, "don't launch with --rm (container will exist after exiting)") runCmd.Flags().BoolVar(&noUSBPtr, "no-usb", false, "don't mount usb devices") runCmd.Flags().BoolVar(&noNethostPtr, "no-nethost", false, "don't launch with --network=host") + runCmd.Flags().StringVar(&othPtr, "other", "", "add the following string to 'run' command.") + runCmd.Flags().StringVar(&devAccPtr, "device-access", "", "add access to the following devices (as stated in https://stackoverflow.com/a/62758958). Format : ;;") + } From 2426d6fbe181687177b7679a1a707eeb9e16e9f6 Mon Sep 17 00:00:00 2001 From: XV25 Date: Tue, 4 Feb 2025 16:14:36 +0100 Subject: [PATCH 02/21] Add option to directly add devices access inside container (such as webcam) --- cmd/root.go | 1 + cmd/run.go | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index f41f3e5..69089e7 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -122,6 +122,7 @@ var ( contNamePtr string othPtr string devAccPtr string + devRMWPtr string logger = log.New(os.Stdout, appname+": ", log.Lmsgprefix) dockerRunArgs = []string{ "--interactive", diff --git a/cmd/run.go b/cmd/run.go index 8b30755..cdb7e09 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -478,6 +478,11 @@ const runExamples = ` - Launch an 3D accelerated GUI (opengl) {{.appname}} run ubuntu -- bash -c "sudo apt install -y mesa-utils && glxgears" + + - Add access to a webcam (ex : /dev/video0) : + + {{.appname}} run ubuntu --device-access "/dev/video0" + ` var ( @@ -709,11 +714,19 @@ Examples: dockerRunArgs = append(dockerRunArgs, "--device-cgroup-rule=c 189:* rmw") - // add commands to include specific usb devices (as stated by https://stackoverflow.com/a/62758958) + // add commands to add rules to specific usb devices (as stated by https://stackoverflow.com/a/62758958) + if devRMWPtr != "" { + var indexes = strings.Split(devRMWPtr, ";") + for i := 0; i < len(indexes); i++ { + var s = "--device-cgroup-rule=c " + indexes[i] + ":* rmw" + dockerRunArgs = append(dockerRunArgs, s) + } + } + // add rules to mount specific usb devices if devAccPtr != "" { var indexes = strings.Split(devAccPtr, ";") for i := 0; i < len(indexes); i++ { - var s = "--device-cgroup-rule=c " + indexes[i] + ":* rmw" + var s = "--device=" + indexes[i] dockerRunArgs = append(dockerRunArgs, s) } } @@ -829,6 +842,7 @@ func init() { runCmd.Flags().BoolVar(&noUSBPtr, "no-usb", false, "don't mount usb devices") runCmd.Flags().BoolVar(&noNethostPtr, "no-nethost", false, "don't launch with --network=host") runCmd.Flags().StringVar(&othPtr, "other", "", "add the following string to 'run' command.") - runCmd.Flags().StringVar(&devAccPtr, "device-access", "", "add access to the following devices (as stated in https://stackoverflow.com/a/62758958). Format : ;;") + runCmd.Flags().StringVar(&devRMWPtr, "device-rmw", "", "add rmw rules to the following devices (as stated in https://stackoverflow.com/a/62758958). Format : ;;") + runCmd.Flags().StringVar(&devAccPtr, "device-access", "", "mount the following devices to container (through --device option). Format : ;") } From 2a396d3f5335c46969aa292d05e70777e49e7212 Mon Sep 17 00:00:00 2001 From: XV25 Date: Tue, 4 Feb 2025 16:16:02 +0100 Subject: [PATCH 03/21] Small typo correction --- cmd/run.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/run.go b/cmd/run.go index cdb7e09..41d6979 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -480,7 +480,7 @@ const runExamples = ` {{.appname}} run ubuntu -- bash -c "sudo apt install -y mesa-utils && glxgears" - Add access to a webcam (ex : /dev/video0) : - + {{.appname}} run ubuntu --device-access "/dev/video0" ` @@ -842,7 +842,7 @@ func init() { runCmd.Flags().BoolVar(&noUSBPtr, "no-usb", false, "don't mount usb devices") runCmd.Flags().BoolVar(&noNethostPtr, "no-nethost", false, "don't launch with --network=host") runCmd.Flags().StringVar(&othPtr, "other", "", "add the following string to 'run' command.") - runCmd.Flags().StringVar(&devRMWPtr, "device-rmw", "", "add rmw rules to the following devices (as stated in https://stackoverflow.com/a/62758958). Format : ;;") + runCmd.Flags().StringVar(&devRMWPtr, "device-rmw", "", "add rmw rules to the following devices (as stated in https://stackoverflow.com/a/62758958). Format : ;") runCmd.Flags().StringVar(&devAccPtr, "device-access", "", "mount the following devices to container (through --device option). Format : ;") } From a6d5afaf86532d90bf4204944f4102df7524e89e Mon Sep 17 00:00:00 2001 From: XV25 Date: Sun, 9 Feb 2025 00:02:05 +0100 Subject: [PATCH 04/21] Add option to desactivate sudo and apt-get at docker run. Also add possibility to set docker-apt-cacher as same distro as the last image run (desactivated for now). --- assets/apt-cacher/Dockerfile | 2 +- assets/createUser.sh.in | 39 +++++++++++++++++++++--------------- cmd/root.go | 1 + cmd/run.go | 31 ++++++++++++++++++++++++++-- 4 files changed, 54 insertions(+), 19 deletions(-) diff --git a/assets/apt-cacher/Dockerfile b/assets/apt-cacher/Dockerfile index 5dddcc4..d87364d 100644 --- a/assets/apt-cacher/Dockerfile +++ b/assets/apt-cacher/Dockerfile @@ -11,7 +11,7 @@ # add this to container: # echo 'Acquire::http { Proxy "http://localhost:3142"; };' >> /etc/apt/apt.conf.d/01proxy # echo 'Acquire::http { Proxy "http://172.17.0.2:3142"; };' >> /etc/apt/apt.conf.d/01proxy -FROM ubuntu:22.04 +#FROM ubuntu:22.04 VOLUME ["/var/cache/apt-cacher-ng"] RUN apt-get update && apt-get install -y apt-cacher-ng \ diff --git a/assets/createUser.sh.in b/assets/createUser.sh.in index 9b985b4..b68a133 100644 --- a/assets/createUser.sh.in +++ b/assets/createUser.sh.in @@ -74,17 +74,21 @@ distro_unknown="" sudo_ok="" installing_packages_msg="installing sudo, tzdata, vim, bash-completion..." if [ -n "${distro_ubuntu}" ] || [ -n "${distro_debian}" ]; then - if [ -n "${distro_ubuntu}" ]; then - echo -n "- Ubuntu distro, " + if [ "{{.setupSudo}}" == true ]; then + if [ -n "${distro_ubuntu}" ]; then + echo -n "- Ubuntu distro, " + else + echo -n "- Debian distro, " + fi + echo "running apt update..." + env DEBIAN_FRONTEND=noninteractive apt-get -qq update > /dev/null + echo "- installing apt-utils" + env DEBIAN_FRONTEND=noninteractive apt-get -qq install apt-utils > /dev/null 2>&1 + echo "- ${installing_packages_msg}" + env DEBIAN_FRONTEND=noninteractive apt-get -qq install sudo tzdata vim bash-completion > /dev/null else - echo -n "- Debian distro, " + sudo_ok=false fi - echo "running apt update..." - env DEBIAN_FRONTEND=noninteractive apt-get -qq update > /dev/null - echo "- installing apt-utils" - env DEBIAN_FRONTEND=noninteractive apt-get -qq install apt-utils > /dev/null 2>&1 - echo "- ${installing_packages_msg}" - env DEBIAN_FRONTEND=noninteractive apt-get -qq install sudo tzdata vim bash-completion > /dev/null elif [ -n "${distro_fedora}" ]; then echo "- Fedora distro, ${installing_packages_msg}" dnf install -y sudo tzdata vim bash-completion > /dev/null @@ -95,31 +99,34 @@ fi if [ -n "${distro_unknown}" ]; then echo "- UNKNOWN distro." echo "failed to install packages sudo tzdata." -else + sudo_ok=false +fi + +if [ "${sudo_ok}" != false ]; then echo "{{.username}} ALL=NOPASSWD: ALL" >> /etc/sudoers.d/dogi sed -i '/secure_path/ s/^/#/' /etc/sudoers - sudo_ok="True" + sudo_ok=true fi ############################################################### echo "- done, happy 🐳!" echo "- you now are INSIDE the container" - +echo "${sudo_ok}" if [ $# -eq 0 ]; then - if [ -n "${sudo_ok}" ]; then + if [ "${sudo_ok}" = true ]; then echo "- switch to user {{.username}}" sudo -EHu {{.username}} bash else - echo "- sudo not setup, will run as root" + echo "- sudo not setup for switch, will run as root" bash fi fi -if [ -n "${sudo_ok}" ]; then +if [ "${sudo_ok}" = true ]; then echo "- run as user: $@" sudo -EHu {{.username}} "$@" else - echo "- sudo not setup, will run as root" + echo "- sudo not setup in run, will run as root" $@ fi diff --git a/cmd/root.go b/cmd/root.go index 69089e7..cae6f3a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -118,6 +118,7 @@ var ( noUSBPtr bool noNethostPtr bool noCacherPtr bool + setupSudoPtr bool workDirPtr string contNamePtr string othPtr string diff --git a/cmd/run.go b/cmd/run.go index 41d6979..03043b0 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -8,6 +8,7 @@ import ( "os/exec" "os/user" "path/filepath" + "strconv" "strings" "syscall" "text/template" @@ -241,7 +242,7 @@ func aptCacherSupported(distro string) bool { return false } -func setAptCacher() string { +func setAptCacher(imageName string) string { baseName := "apt-cacher" imgName := fmt.Sprintf("%s/%s", appname, baseName) @@ -253,6 +254,29 @@ func setAptCacher() string { defer os.RemoveAll(dir) // clean up tmpfn := filepath.Join(dir, "Dockerfile") + var version = "ubuntu:22.04" + var changeAptDistro = false + + if changeAptDistro { + // create apt-cacher image with the same distro + // as the docker image created + // (it might be the cause of some bugs, so let it as an option + // for now) + // get distro of the image + outN, errN := exec.Command("docker", "run", "--rm", "--tty", + "--entrypoint=cat", + imageName, "/etc/issue").Output() + check(errN) + var distroInfo = strings.Split(string(outN), "\n")[0] + logger.Println(distroInfo) + if strings.Contains(distroInfo, "Ubuntu") { + var number = strings.Split(string(outN), " ")[1] + version = "ubuntu:" + number[:5] + logger.Println(version) + } + } + + assets.AptCacheDockerfile = "FROM " + version + "\n" + assets.AptCacheDockerfile check(os.WriteFile(tmpfn, []byte(assets.AptCacheDockerfile), 0666)) logger.Printf("temp dir: %s\n", dir) logger.Printf("temp Dockerfile: %s\n", tmpfn) @@ -651,7 +675,7 @@ Examples: if aptCacherSupported(distro) { if !noCacherPtr { logger.Println("using apt-cacher, disable it with --no-cacher") - file := setAptCacher() + file := setAptCacher(imageName) addCopyToContainerFile(file, "/etc/apt/apt.conf.d/01proxy") } else { logger.Println("disabling apt-cacher (--no-cacher=ON)") @@ -763,6 +787,7 @@ Examples: check(err) logger.Println("create user script:", createUserFile.Name()) { + //logger.Println("setupsudo : ", strconv.FormatBool(setupSudoPtr)) groupsCmd := userSingleton().createGroupsCmd() err := template.Must(template.New("").Option("missingkey=error").Parse(assets.CreateUserTemplate)).Execute(createUserFile, map[string]string{"username": userObj.Username, @@ -772,6 +797,7 @@ Examples: "gnames": groupsCmd.gnames, "Name": userObj.Name, "createGroups": groupsCmd.cmd, + "setupSudo": strconv.FormatBool(setupSudoPtr), }) check(err) } @@ -844,5 +870,6 @@ func init() { runCmd.Flags().StringVar(&othPtr, "other", "", "add the following string to 'run' command.") runCmd.Flags().StringVar(&devRMWPtr, "device-rmw", "", "add rmw rules to the following devices (as stated in https://stackoverflow.com/a/62758958). Format : ;") runCmd.Flags().StringVar(&devAccPtr, "device-access", "", "mount the following devices to container (through --device option). Format : ;") + runCmd.Flags().BoolVar(&setupSudoPtr, "setup-sudo", true, "install inside containers various basic packages, such as apt-utils, sudo, tzdata, vim, or bash-completion.") } From 678d8ef0565d49d5607c131c8e7e251a5150fccb Mon Sep 17 00:00:00 2001 From: XV25 Date: Thu, 3 Apr 2025 14:24:00 +0200 Subject: [PATCH 05/21] Add more debugging instructions in readme, manage a bug for too basic images (typically, without "/usr/bin" folder; it is the case for "hello-world" image). --- README.md | 12 ++++++++++++ assets/apt-cacher/Dockerfile | 2 +- cmd/run.go | 9 ++++++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bb3e119..0c4966a 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,18 @@ It allows using rootless containers, running GUIs, quickly mounting your current Even though **dogi** was originally inspired by [rocker](https://github.com/osrf/rocker) and solves a similar problem (or the same), it aims to do so with minimum user effort. Additionally, it provides the ability to interact with the `docker` client directly ([transparent](#design-principles)). +## !!! WARNING !!! + +* Dogi's processes assume that Docker is able to build an image in the /tmp folder. This is typically verified if Docker is installed via the procedure described on the following pages: https://docs.docker.com/engine/install/ubuntu/ ; https://docs.docker.com/engine/install/linux-postinstall/ . This is typically not checked if Docker is installed via snap. + +* For now, Dogi only works for images based on these distros: Ubuntu, Debian, Fedora. Dogi also won't work for images that are too simplistic (typically, the “hello-world” Docker image). + +* In order to use Docker (and thus, Dogi) with GPU support, you need to follow the installation prerequisites instructions (https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#prerequisites), and the subsequents configuration instructions (https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#configuration). Otherwise, the following bug will appears : + +``` +Bug : Error response from daemon: unknown or invalid runtime name: nvidia +``` + ## Quickstart ```bash diff --git a/assets/apt-cacher/Dockerfile b/assets/apt-cacher/Dockerfile index d87364d..11d3af5 100644 --- a/assets/apt-cacher/Dockerfile +++ b/assets/apt-cacher/Dockerfile @@ -11,7 +11,7 @@ # add this to container: # echo 'Acquire::http { Proxy "http://localhost:3142"; };' >> /etc/apt/apt.conf.d/01proxy # echo 'Acquire::http { Proxy "http://172.17.0.2:3142"; };' >> /etc/apt/apt.conf.d/01proxy -#FROM ubuntu:22.04 +# FROM ubuntu:22.04 VOLUME ["/var/cache/apt-cacher-ng"] RUN apt-get update && apt-get install -y apt-cacher-ng \ diff --git a/cmd/run.go b/cmd/run.go index 03043b0..1c779bc 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -223,7 +223,14 @@ func imageDistro(imageName string) string { out, err := exec.Command("docker", "run", "--rm", "--tty", "--entrypoint=cat", imageName, "/etc/os-release").Output() - check(err) + // Debug for barebone images, where image distro could not + // even be checked + if err != nil { + logger.Printf("Error : could not check image distro. Recorded error : ") + logger.Println(err.Error()) + logger.Fatalf("We'll assume the image is too basic for dogi. Exiting...") + } + //check(err) for _, val := range supportedDistros() { if strings.Contains(string(out), val) { From b7e9fd8b3f276f33689b9bafeed3c3e005817862 Mon Sep 17 00:00:00 2001 From: XV25 Date: Fri, 4 Apr 2025 16:17:47 +0200 Subject: [PATCH 06/21] Add option to change temporary directory for temp files. It can be used as a debugging tool to identity whether there is permission issues with /tmp folder --- cmd/root.go | 1 + cmd/run.go | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index cae6f3a..d54a7a9 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -124,6 +124,7 @@ var ( othPtr string devAccPtr string devRMWPtr string + tempDirPtr string logger = log.New(os.Stdout, appname+": ", log.Lmsgprefix) dockerRunArgs = []string{ "--interactive", diff --git a/cmd/run.go b/cmd/run.go index 1c779bc..6559f68 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -256,7 +256,8 @@ func setAptCacher(imageName string) string { { logger.Printf("build apt cacher image: %s\n", imgName) // build apt-cache-ng image - dir, err := os.MkdirTemp("", "dogi_apt-cache") + //dir, err := os.MkdirTemp("", "dogi_apt-cache") + dir, err := os.MkdirTemp(tempDirPtr, "dogi_apt-cache") check(err) defer os.RemoveAll(dir) // clean up @@ -368,7 +369,7 @@ func setAptCacher(imageName string) string { aptCacherConf := fmt.Sprintf("Acquire::http { Proxy \"http://%s:3142\"; };", ip) - aptCacherFile, err := os.CreateTemp("", fmt.Sprintf(".%s_%s_*", appname, baseName)) + aptCacherFile, err := os.CreateTemp(tempDirPtr, fmt.Sprintf(".%s_%s_*", appname, baseName)) check(err) logger.Printf("apt-cacher file: %s", aptCacherFile.Name()) check(os.WriteFile(aptCacherFile.Name(), []byte(aptCacherConf), 0666)) @@ -566,7 +567,9 @@ Examples: check(err) // create xauth magic cookie file - xauthfile, err := os.CreateTemp("", fmt.Sprintf(".%s*.xauth", appname)) + //xauthfile, err := os.CreateTemp("", fmt.Sprintf(".%s*.xauth", appname)) + xauthfile, err := os.CreateTemp(tempDirPtr, fmt.Sprintf(".%s*.xauth", appname)) + check(err) logger.Println("temp xauth file:", xauthfile.Name()) addCopyToContainerFile(xauthfile.Name(), "/.xauth") @@ -595,7 +598,8 @@ Examples: logger.Printf("workdir: %s\n", workDirPtr) mountStrs := []string{fmt.Sprintf("--volume=%s:%s", workDirPtr, workDirPtr)} - cidFile := fmt.Sprintf("%s/.%s%v.cid", os.TempDir(), appname, rand.Int63()) + //cidFile := fmt.Sprintf("%s/.%s%v.cid", os.TempDir(), appname, rand.Int63()) + cidFile := fmt.Sprintf("%s/.%s%v.cid", tempDirPtr, appname, rand.Int63()) mountStrs = append(mountStrs, fmt.Sprintf("--cidfile=%s", cidFile)) mountStrs = append(mountStrs, fmt.Sprintf("--volume=%s:%s", cidFile, cidFileContainer)) @@ -789,7 +793,9 @@ Examples: // TODO: createUser file won't be removed because // process is replaced at Exec, is there a way? - createUserFile, err := os.CreateTemp("", + // createUserFile, err := os.CreateTemp("", + // fmt.Sprintf(".%s*.sh", appname)) + createUserFile, err := os.CreateTemp(tempDirPtr, fmt.Sprintf(".%s*.sh", appname)) check(err) logger.Println("create user script:", createUserFile.Name()) @@ -878,5 +884,5 @@ func init() { runCmd.Flags().StringVar(&devRMWPtr, "device-rmw", "", "add rmw rules to the following devices (as stated in https://stackoverflow.com/a/62758958). Format : ;") runCmd.Flags().StringVar(&devAccPtr, "device-access", "", "mount the following devices to container (through --device option). Format : ;") runCmd.Flags().BoolVar(&setupSudoPtr, "setup-sudo", true, "install inside containers various basic packages, such as apt-utils, sudo, tzdata, vim, or bash-completion.") - + runCmd.Flags().StringVar(&tempDirPtr, "temp-dir", "", "temporary directory to use for dogi (default: $TMPDIR or /tmp, through empty command). Can be modified if there are access issues with this particular folder.") } From 78d58347773c144a36af3923e71addc53b158cfa Mon Sep 17 00:00:00 2001 From: XV25 Date: Fri, 4 Apr 2025 16:37:37 +0200 Subject: [PATCH 07/21] Suppressed option for setting apt-cacher distro (not useful, and source of bugs). --- assets/apt-cacher/Dockerfile | 2 +- cmd/run.go | 23 ----------------------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/assets/apt-cacher/Dockerfile b/assets/apt-cacher/Dockerfile index 11d3af5..938f657 100644 --- a/assets/apt-cacher/Dockerfile +++ b/assets/apt-cacher/Dockerfile @@ -11,7 +11,7 @@ # add this to container: # echo 'Acquire::http { Proxy "http://localhost:3142"; };' >> /etc/apt/apt.conf.d/01proxy # echo 'Acquire::http { Proxy "http://172.17.0.2:3142"; };' >> /etc/apt/apt.conf.d/01proxy -# FROM ubuntu:22.04 +FROM ubuntu:22.04 VOLUME ["/var/cache/apt-cacher-ng"] RUN apt-get update && apt-get install -y apt-cacher-ng \ diff --git a/cmd/run.go b/cmd/run.go index 6559f68..95bde31 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -262,29 +262,6 @@ func setAptCacher(imageName string) string { defer os.RemoveAll(dir) // clean up tmpfn := filepath.Join(dir, "Dockerfile") - var version = "ubuntu:22.04" - var changeAptDistro = false - - if changeAptDistro { - // create apt-cacher image with the same distro - // as the docker image created - // (it might be the cause of some bugs, so let it as an option - // for now) - // get distro of the image - outN, errN := exec.Command("docker", "run", "--rm", "--tty", - "--entrypoint=cat", - imageName, "/etc/issue").Output() - check(errN) - var distroInfo = strings.Split(string(outN), "\n")[0] - logger.Println(distroInfo) - if strings.Contains(distroInfo, "Ubuntu") { - var number = strings.Split(string(outN), " ")[1] - version = "ubuntu:" + number[:5] - logger.Println(version) - } - } - - assets.AptCacheDockerfile = "FROM " + version + "\n" + assets.AptCacheDockerfile check(os.WriteFile(tmpfn, []byte(assets.AptCacheDockerfile), 0666)) logger.Printf("temp dir: %s\n", dir) logger.Printf("temp Dockerfile: %s\n", tmpfn) From 5137a5e3b6de9b6b71cb297fdbaa992008fad62e Mon Sep 17 00:00:00 2001 From: XV25 Date: Fri, 4 Apr 2025 16:42:34 +0200 Subject: [PATCH 08/21] Small cleanup --- cmd/run.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/run.go b/cmd/run.go index 95bde31..9e347e5 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -249,7 +249,7 @@ func aptCacherSupported(distro string) bool { return false } -func setAptCacher(imageName string) string { +func setAptCacher() string { baseName := "apt-cacher" imgName := fmt.Sprintf("%s/%s", appname, baseName) @@ -663,7 +663,7 @@ Examples: if aptCacherSupported(distro) { if !noCacherPtr { logger.Println("using apt-cacher, disable it with --no-cacher") - file := setAptCacher(imageName) + file := setAptCacher() addCopyToContainerFile(file, "/etc/apt/apt.conf.d/01proxy") } else { logger.Println("disabling apt-cacher (--no-cacher=ON)") @@ -777,7 +777,6 @@ Examples: check(err) logger.Println("create user script:", createUserFile.Name()) { - //logger.Println("setupsudo : ", strconv.FormatBool(setupSudoPtr)) groupsCmd := userSingleton().createGroupsCmd() err := template.Must(template.New("").Option("missingkey=error").Parse(assets.CreateUserTemplate)).Execute(createUserFile, map[string]string{"username": userObj.Username, From c634efadf4aaa0ad70bfc2f28d4011b2a6a3f5d4 Mon Sep 17 00:00:00 2001 From: XV25 Date: Tue, 8 Apr 2025 09:40:07 +0200 Subject: [PATCH 09/21] Quick fix for "--temp-dir" feature (.cid file didn't take into account the path for /tmp). --- cmd/run.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmd/run.go b/cmd/run.go index 9e347e5..851ccac 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -576,6 +576,9 @@ Examples: mountStrs := []string{fmt.Sprintf("--volume=%s:%s", workDirPtr, workDirPtr)} //cidFile := fmt.Sprintf("%s/.%s%v.cid", os.TempDir(), appname, rand.Int63()) + if tempDirPtr == "" { + tempDirPtr = os.TempDir() + } cidFile := fmt.Sprintf("%s/.%s%v.cid", tempDirPtr, appname, rand.Int63()) mountStrs = append(mountStrs, fmt.Sprintf("--cidfile=%s", cidFile)) mountStrs = append(mountStrs, fmt.Sprintf("--volume=%s:%s", cidFile, cidFileContainer)) @@ -811,6 +814,10 @@ Examples: dockerCreateArgs := merge([]string{dockerCmd, "create"}, dockerRunArgs) + logger.Println("Docker tempDir : ", tempDirPtr) + if tempDirPtr == "" { + logger.Println("Is recognized as empty") + } logger.Println("docker command: ", strings.Join(merge(mergeEscapeSpaces(dockerCreateArgs), entrypoint), " ")) dockerArgs := merge(dockerCreateArgs, entrypoint) From 13509ec3be91636bc170dc16af1f2832093a4678 Mon Sep 17 00:00:00 2001 From: XV25 Date: Tue, 8 Apr 2025 09:46:32 +0200 Subject: [PATCH 10/21] Quick cleanup --- cmd/run.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmd/run.go b/cmd/run.go index 851ccac..7bd0796 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -814,10 +814,6 @@ Examples: dockerCreateArgs := merge([]string{dockerCmd, "create"}, dockerRunArgs) - logger.Println("Docker tempDir : ", tempDirPtr) - if tempDirPtr == "" { - logger.Println("Is recognized as empty") - } logger.Println("docker command: ", strings.Join(merge(mergeEscapeSpaces(dockerCreateArgs), entrypoint), " ")) dockerArgs := merge(dockerCreateArgs, entrypoint) From c524a077962637a8dc4432dbc261ffe84cd86829 Mon Sep 17 00:00:00 2001 From: XV25 Date: Thu, 22 May 2025 17:16:11 +0200 Subject: [PATCH 11/21] Correct a bug with --other option --- assets/apt-cacher/Dockerfile | 9 +++++++++ cmd/run.go | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/assets/apt-cacher/Dockerfile b/assets/apt-cacher/Dockerfile index 938f657..b9f3415 100644 --- a/assets/apt-cacher/Dockerfile +++ b/assets/apt-cacher/Dockerfile @@ -14,6 +14,15 @@ FROM ubuntu:22.04 VOLUME ["/var/cache/apt-cacher-ng"] + +## Added : Try to clean everything (for bug : apt-get BADSIG GPG) +RUN apt-get clean && \ + cd /var/lib/apt &&\ + mv lists lists.old &&\ + mkdir -p lists/partial && \ + apt-get clean &&\ + apt-get update -qq -y + RUN apt-get update && apt-get install -y apt-cacher-ng \ && sed -i 's/\# PassThroughPattern: \.\*/PassThroughPattern: \.\*/g' /etc/apt-cacher-ng/acng.conf diff --git a/cmd/run.go b/cmd/run.go index 7bd0796..0f55546 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -802,7 +802,10 @@ Examples: if othPtr != "" { // add final custom commands. - dockerRunArgs = append(dockerRunArgs, othPtr) + outStr := strings.Split(othPtr, " ") + for _, elmt := range outStr { + dockerRunArgs = append(dockerRunArgs, elmt) + } } dockerRunArgs = append(dockerRunArgs, imageName) From e351c3a864ec4719286be7404410ef47b2da3430 Mon Sep 17 00:00:00 2001 From: XV25 Date: Fri, 23 May 2025 09:12:31 +0200 Subject: [PATCH 12/21] Add --ipc==host and --pid==host options (necessary to make container ROS work with --network==host). --- cmd/root.go | 1 + cmd/run.go | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/cmd/root.go b/cmd/root.go index d54a7a9..a5afb56 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -119,6 +119,7 @@ var ( noNethostPtr bool noCacherPtr bool setupSudoPtr bool + pidIPCHostPtr bool workDirPtr string contNamePtr string othPtr string diff --git a/cmd/run.go b/cmd/run.go index 0f55546..90e4699 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -637,6 +637,12 @@ Examples: if !noNethostPtr { logger.Println("adding --network=host") dockerRunArgs = append(dockerRunArgs, "--network=host") + if pidIPCHostPtr { + // https://github.com/eProsima/Fast-DDS/issues/2956 + logger.Println("adding --pid=host and --ipc=host") + dockerRunArgs = append(dockerRunArgs, "--pid=host") + dockerRunArgs = append(dockerRunArgs, "--ipc=host") + } } if privilegedPtr { @@ -867,4 +873,6 @@ func init() { runCmd.Flags().StringVar(&devAccPtr, "device-access", "", "mount the following devices to container (through --device option). Format : ;") runCmd.Flags().BoolVar(&setupSudoPtr, "setup-sudo", true, "install inside containers various basic packages, such as apt-utils, sudo, tzdata, vim, or bash-completion.") runCmd.Flags().StringVar(&tempDirPtr, "temp-dir", "", "temporary directory to use for dogi (default: $TMPDIR or /tmp, through empty command). Can be modified if there are access issues with this particular folder.") + runCmd.Flags().BoolVar(&pidIPCHostPtr, "pidipc-host", true, "add --pid=host (PID of the container) and --ipc=host (Memory Access) to docker run command. Automatically activated with --network=host. Although it removes a security layer, it is notably necessary to let ROS containers communicates between them in --network=host mode.") + } From 9c4110c78cfdcb2d0a3a7ebfe5827e1e847aace2 Mon Sep 17 00:00:00 2001 From: XV25 Date: Mon, 26 May 2025 15:52:10 +0200 Subject: [PATCH 13/21] Quick modification to be sure that the desactivation of sudo / others works. --- cmd/root.go | 2 +- cmd/run.go | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index a5afb56..6c3d42b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -118,7 +118,7 @@ var ( noUSBPtr bool noNethostPtr bool noCacherPtr bool - setupSudoPtr bool + noSetupSudoPtr bool pidIPCHostPtr bool workDirPtr string contNamePtr string diff --git a/cmd/run.go b/cmd/run.go index 90e4699..2973c74 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -786,6 +786,12 @@ Examples: check(err) logger.Println("create user script:", createUserFile.Name()) { + //logger.Println(strconv.FormatBool(setupSudoPtr)) + var setupSudo bool = true + if noSetupSudoPtr { + setupSudo = false + } + groupsCmd := userSingleton().createGroupsCmd() err := template.Must(template.New("").Option("missingkey=error").Parse(assets.CreateUserTemplate)).Execute(createUserFile, map[string]string{"username": userObj.Username, @@ -795,7 +801,7 @@ Examples: "gnames": groupsCmd.gnames, "Name": userObj.Name, "createGroups": groupsCmd.cmd, - "setupSudo": strconv.FormatBool(setupSudoPtr), + "setupSudo": strconv.FormatBool(setupSudo), }) check(err) } @@ -871,7 +877,7 @@ func init() { runCmd.Flags().StringVar(&othPtr, "other", "", "add the following string to 'run' command.") runCmd.Flags().StringVar(&devRMWPtr, "device-rmw", "", "add rmw rules to the following devices (as stated in https://stackoverflow.com/a/62758958). Format : ;") runCmd.Flags().StringVar(&devAccPtr, "device-access", "", "mount the following devices to container (through --device option). Format : ;") - runCmd.Flags().BoolVar(&setupSudoPtr, "setup-sudo", true, "install inside containers various basic packages, such as apt-utils, sudo, tzdata, vim, or bash-completion.") + runCmd.Flags().BoolVar(&noSetupSudoPtr, "no-setup-sudo", false, "install inside containers various basic packages, such as apt-utils, sudo, tzdata, vim, or bash-completion.") runCmd.Flags().StringVar(&tempDirPtr, "temp-dir", "", "temporary directory to use for dogi (default: $TMPDIR or /tmp, through empty command). Can be modified if there are access issues with this particular folder.") runCmd.Flags().BoolVar(&pidIPCHostPtr, "pidipc-host", true, "add --pid=host (PID of the container) and --ipc=host (Memory Access) to docker run command. Automatically activated with --network=host. Although it removes a security layer, it is notably necessary to let ROS containers communicates between them in --network=host mode.") From c6e4d440a7608a259b3088b9d1f2025f093762db Mon Sep 17 00:00:00 2001 From: Nicolas Torres Date: Tue, 5 Aug 2025 21:00:16 +0200 Subject: [PATCH 14/21] simplify readme --- README.md | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 0c4966a..f74d166 100644 --- a/README.md +++ b/README.md @@ -14,19 +14,6 @@ It allows using rootless containers, running GUIs, quickly mounting your current Even though **dogi** was originally inspired by [rocker](https://github.com/osrf/rocker) and solves a similar problem (or the same), it aims to do so with minimum user effort. Additionally, it provides the ability to interact with the `docker` client directly ([transparent](#design-principles)). -## !!! WARNING !!! - -* Dogi's processes assume that Docker is able to build an image in the /tmp folder. This is typically verified if Docker is installed via the procedure described on the following pages: https://docs.docker.com/engine/install/ubuntu/ ; https://docs.docker.com/engine/install/linux-postinstall/ . This is typically not checked if Docker is installed via snap. - -* For now, Dogi only works for images based on these distros: Ubuntu, Debian, Fedora. Dogi also won't work for images that are too simplistic (typically, the “hello-world” Docker image). - -* In order to use Docker (and thus, Dogi) with GPU support, you need to follow the installation prerequisites instructions (https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#prerequisites), and the subsequents configuration instructions (https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#configuration). Otherwise, the following bug will appears : - -``` -Bug : Error response from daemon: unknown or invalid runtime name: nvidia -``` - -## Quickstart ```bash # install binary @@ -47,6 +34,22 @@ Some [optional setup steps](#optional-setup-steps) might be required. **NOTE:** You can also install from source: `CGO_ENABLED=0 go install -a github.com/ntorresalberto/dogi@latest` +### Requirements + +**dogi** relies on the docker engine CLI for its operations. Before using dogi, make sure: + +* You have installed [docker engine via the official guide](https://docs.docker.com/engine/install/ubuntu/). Docker installed through snap won't work, because **dogi** sometimes creates files and uses `/tmp`. +* You have the correct permissions to call docker cli withotu sudo. This can be setup with the [post-installation steps](https://docs.docker.com/engine/install/linux-postinstall/). +* In order to use docker (and **dogi**) with GPU support, you must first [follow the installation prerequisites instructions](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#prerequisites), and the [configuration instructions](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#configuration). Otherwise, the following bug will appears : + +``` +docker : Error response from daemon: unknown or invalid runtime name: nvidia +``` + +## Quickstart + + + --- - [Examples](#examples) @@ -127,7 +130,7 @@ You should find **dogi** useful if you: - **transparent**: **dogi** forwards any unrecognized arguments to docker, in case you ever need to do anything not currently supported. - **simple**: aims to cover the most common use cases with the least user intervention (you shouldn't need to pass any extra flags/options most of the time). If you don't agree with the defaults, [please say so](https://github.com/ntorresalberto/dogi/issues/new). -- **secure**: there are [many ways](http://wiki.ros.org/docker/Tutorials/GUI) to expose the xorg server to containers, **dogi** tries to do it in the most secure way. Additionally, it proposes an easy way to avoid the potentially dangerous practice of root containers. +- **secure**: there are [many ways](http://wiki.ros.org/docker/Tutorials/GUI) to expose the xorg server to containers, **dogi** tries to do it in the most secure way. Additionally, it proposes an easy way to avoid the potentially dangerous practice of root containers. - **minimalist**: **dogi** thrives to have the least amount of dependencies and not do more than it needs. > Many (open source) hackers are proud if they achieve large amounts of code, because they believe the more lines of code they've written, the more progress they have made. The more progress they have made, the more skilled they are. This is simply a delusion. @@ -136,7 +139,8 @@ You should find **dogi** useful if you: ### Limitations -- Only supports ubuntu-based images (because of apt commands used) +- Only supports debian-based images like ubuntu (because of apt commands used) and more recently fedora. + - Only supports X11 environments for GUI applications (because of xorg socket communication)
@@ -186,4 +190,3 @@ source .bashrc This error is usually caused by a container running an older version of glibc than your host system (where you compiled `dogi`). A possible cause of this is you didn't use `CGO_ENABLED=0` in the `go install`, as specified in #quickstart. - From fc29bf2e7a791e05e86df6c24768540f4c867786 Mon Sep 17 00:00:00 2001 From: Nicolas Torres Date: Wed, 6 Aug 2025 22:52:59 +0200 Subject: [PATCH 15/21] improve message when distro check fails --- cmd/run.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/run.go b/cmd/run.go index 2973c74..fa3a1e5 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -223,14 +223,14 @@ func imageDistro(imageName string) string { out, err := exec.Command("docker", "run", "--rm", "--tty", "--entrypoint=cat", imageName, "/etc/os-release").Output() - // Debug for barebone images, where image distro could not - // even be checked if err != nil { - logger.Printf("Error : could not check image distro. Recorded error : ") - logger.Println(err.Error()) - logger.Fatalf("We'll assume the image is too basic for dogi. Exiting...") + logger.Println("Error: failed to verify image distro:") + logger.Printf("image: %s\n", imageName) + logger.Printf("error: %s\n", err.Error()) + logger.Printf("Please share this log the %s devs at:\n", appname) + logger.Fatalf("https://github.com/ntorresalberto/dogi/issues/new") } - //check(err) + check(err) for _, val := range supportedDistros() { if strings.Contains(string(out), val) { From 5c09b82f598eea308e7f63c7156dba450410ba3a Mon Sep 17 00:00:00 2001 From: Nicolas Torres Date: Wed, 6 Aug 2025 23:03:43 +0200 Subject: [PATCH 16/21] comment apt-cacher-ng workaround until confirmed to be the solution --- assets/apt-cacher/Dockerfile | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/assets/apt-cacher/Dockerfile b/assets/apt-cacher/Dockerfile index b9f3415..ce7f918 100644 --- a/assets/apt-cacher/Dockerfile +++ b/assets/apt-cacher/Dockerfile @@ -15,13 +15,14 @@ FROM ubuntu:22.04 VOLUME ["/var/cache/apt-cacher-ng"] -## Added : Try to clean everything (for bug : apt-get BADSIG GPG) -RUN apt-get clean && \ - cd /var/lib/apt &&\ - mv lists lists.old &&\ - mkdir -p lists/partial && \ - apt-get clean &&\ - apt-get update -qq -y +# TODO left commented until we can confirm this is a workaround +# ## Added : Try to clean everything (for bug : apt-get BADSIG GPG) +# RUN apt-get clean && \ +# cd /var/lib/apt &&\ +# mv lists lists.old &&\ +# mkdir -p lists/partial && \ +# apt-get clean &&\ +# apt-get update -qq -y RUN apt-get update && apt-get install -y apt-cacher-ng \ && sed -i 's/\# PassThroughPattern: \.\*/PassThroughPattern: \.\*/g' /etc/apt-cacher-ng/acng.conf From edfacaeedafd4eefc1e35a47d98b95e66e0302fc Mon Sep 17 00:00:00 2001 From: Nicolas Torres Date: Wed, 6 Aug 2025 23:10:45 +0200 Subject: [PATCH 17/21] enable --pid=host --ipc=host by default, disable with --no-pid-ipc-host --- cmd/root.go | 2 +- cmd/run.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 6c3d42b..9e37d64 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -119,7 +119,7 @@ var ( noNethostPtr bool noCacherPtr bool noSetupSudoPtr bool - pidIPCHostPtr bool + noPIDIPCHostPtr bool workDirPtr string contNamePtr string othPtr string diff --git a/cmd/run.go b/cmd/run.go index fa3a1e5..16d54a3 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -637,9 +637,9 @@ Examples: if !noNethostPtr { logger.Println("adding --network=host") dockerRunArgs = append(dockerRunArgs, "--network=host") - if pidIPCHostPtr { - // https://github.com/eProsima/Fast-DDS/issues/2956 - logger.Println("adding --pid=host and --ipc=host") + if noPIDIPCHostPtr { + // useful for https://github.com/eProsima/Fast-DDS/issues/2956 + logger.Println("add --pid=host --ipc=host, to disable use --no-pid-ipc-host") dockerRunArgs = append(dockerRunArgs, "--pid=host") dockerRunArgs = append(dockerRunArgs, "--ipc=host") } @@ -879,6 +879,6 @@ func init() { runCmd.Flags().StringVar(&devAccPtr, "device-access", "", "mount the following devices to container (through --device option). Format : ;") runCmd.Flags().BoolVar(&noSetupSudoPtr, "no-setup-sudo", false, "install inside containers various basic packages, such as apt-utils, sudo, tzdata, vim, or bash-completion.") runCmd.Flags().StringVar(&tempDirPtr, "temp-dir", "", "temporary directory to use for dogi (default: $TMPDIR or /tmp, through empty command). Can be modified if there are access issues with this particular folder.") - runCmd.Flags().BoolVar(&pidIPCHostPtr, "pidipc-host", true, "add --pid=host (PID of the container) and --ipc=host (Memory Access) to docker run command. Automatically activated with --network=host. Although it removes a security layer, it is notably necessary to let ROS containers communicates between them in --network=host mode.") + runCmd.Flags().BoolVar(&noPIDIPCHostPtr, "no-pid-ipc-host", true, "don't launch with --pid=host --ipc=host.") } From 167549e82c43ad2fef2730117809695df93d4ba4 Mon Sep 17 00:00:00 2001 From: Nicolas Torres Date: Thu, 15 Jan 2026 23:00:07 +0100 Subject: [PATCH 18/21] remove noSetupSudo flag (redudant with noUser) and fix some lint errors --- assets/createUser.sh.in | 39 ++++++++++++++++----------------------- cmd/root.go | 3 +-- cmd/run.go | 20 +++++--------------- 3 files changed, 22 insertions(+), 40 deletions(-) diff --git a/assets/createUser.sh.in b/assets/createUser.sh.in index b68a133..9b985b4 100644 --- a/assets/createUser.sh.in +++ b/assets/createUser.sh.in @@ -74,21 +74,17 @@ distro_unknown="" sudo_ok="" installing_packages_msg="installing sudo, tzdata, vim, bash-completion..." if [ -n "${distro_ubuntu}" ] || [ -n "${distro_debian}" ]; then - if [ "{{.setupSudo}}" == true ]; then - if [ -n "${distro_ubuntu}" ]; then - echo -n "- Ubuntu distro, " - else - echo -n "- Debian distro, " - fi - echo "running apt update..." - env DEBIAN_FRONTEND=noninteractive apt-get -qq update > /dev/null - echo "- installing apt-utils" - env DEBIAN_FRONTEND=noninteractive apt-get -qq install apt-utils > /dev/null 2>&1 - echo "- ${installing_packages_msg}" - env DEBIAN_FRONTEND=noninteractive apt-get -qq install sudo tzdata vim bash-completion > /dev/null + if [ -n "${distro_ubuntu}" ]; then + echo -n "- Ubuntu distro, " else - sudo_ok=false + echo -n "- Debian distro, " fi + echo "running apt update..." + env DEBIAN_FRONTEND=noninteractive apt-get -qq update > /dev/null + echo "- installing apt-utils" + env DEBIAN_FRONTEND=noninteractive apt-get -qq install apt-utils > /dev/null 2>&1 + echo "- ${installing_packages_msg}" + env DEBIAN_FRONTEND=noninteractive apt-get -qq install sudo tzdata vim bash-completion > /dev/null elif [ -n "${distro_fedora}" ]; then echo "- Fedora distro, ${installing_packages_msg}" dnf install -y sudo tzdata vim bash-completion > /dev/null @@ -99,34 +95,31 @@ fi if [ -n "${distro_unknown}" ]; then echo "- UNKNOWN distro." echo "failed to install packages sudo tzdata." - sudo_ok=false -fi - -if [ "${sudo_ok}" != false ]; then +else echo "{{.username}} ALL=NOPASSWD: ALL" >> /etc/sudoers.d/dogi sed -i '/secure_path/ s/^/#/' /etc/sudoers - sudo_ok=true + sudo_ok="True" fi ############################################################### echo "- done, happy 🐳!" echo "- you now are INSIDE the container" -echo "${sudo_ok}" + if [ $# -eq 0 ]; then - if [ "${sudo_ok}" = true ]; then + if [ -n "${sudo_ok}" ]; then echo "- switch to user {{.username}}" sudo -EHu {{.username}} bash else - echo "- sudo not setup for switch, will run as root" + echo "- sudo not setup, will run as root" bash fi fi -if [ "${sudo_ok}" = true ]; then +if [ -n "${sudo_ok}" ]; then echo "- run as user: $@" sudo -EHu {{.username}} "$@" else - echo "- sudo not setup in run, will run as root" + echo "- sudo not setup, will run as root" $@ fi diff --git a/cmd/root.go b/cmd/root.go index 9e37d64..7fb8174 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -118,7 +118,6 @@ var ( noUSBPtr bool noNethostPtr bool noCacherPtr bool - noSetupSudoPtr bool noPIDIPCHostPtr bool workDirPtr string contNamePtr string @@ -192,7 +191,7 @@ Examples: func panicKey(key string, mapWithoutKey map[string]string) { if _, ok := mapWithoutKey[key]; ok { - panic(fmt.Errorf("%s should not exist in this dictionary\n", key)) + panic(fmt.Errorf("%s should not exist in this dictionary", key)) } } diff --git a/cmd/run.go b/cmd/run.go index 16d54a3..391708e 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -8,7 +8,6 @@ import ( "os/exec" "os/user" "path/filepath" - "strconv" "strings" "syscall" "text/template" @@ -259,8 +258,6 @@ func setAptCacher() string { //dir, err := os.MkdirTemp("", "dogi_apt-cache") dir, err := os.MkdirTemp(tempDirPtr, "dogi_apt-cache") check(err) - defer os.RemoveAll(dir) // clean up - tmpfn := filepath.Join(dir, "Dockerfile") check(os.WriteFile(tmpfn, []byte(assets.AptCacheDockerfile), 0666)) logger.Printf("temp dir: %s\n", dir) @@ -274,6 +271,8 @@ func setAptCacher() string { fmt.Println(string(out)) panic(err) } + + check(os.RemoveAll(dir)) // clean up } // launch apt-cacher container @@ -320,8 +319,9 @@ func setAptCacher() string { } // find out apt-cacher ip + // is it possible to have multiple IPs for this container? out, err := exec.Command("docker", "container", - "inspect", "-f", "{{ .NetworkSettings.IPAddress }}", contName).Output() + "inspect", "-f", "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}", contName).Output() if err != nil { logger.Printf("container %s not found, launching...", contName) _, err = exec.Command("docker", @@ -786,12 +786,6 @@ Examples: check(err) logger.Println("create user script:", createUserFile.Name()) { - //logger.Println(strconv.FormatBool(setupSudoPtr)) - var setupSudo bool = true - if noSetupSudoPtr { - setupSudo = false - } - groupsCmd := userSingleton().createGroupsCmd() err := template.Must(template.New("").Option("missingkey=error").Parse(assets.CreateUserTemplate)).Execute(createUserFile, map[string]string{"username": userObj.Username, @@ -801,7 +795,6 @@ Examples: "gnames": groupsCmd.gnames, "Name": userObj.Name, "createGroups": groupsCmd.cmd, - "setupSudo": strconv.FormatBool(setupSudo), }) check(err) } @@ -815,9 +808,7 @@ Examples: if othPtr != "" { // add final custom commands. outStr := strings.Split(othPtr, " ") - for _, elmt := range outStr { - dockerRunArgs = append(dockerRunArgs, elmt) - } + dockerRunArgs = append(dockerRunArgs, outStr...) } dockerRunArgs = append(dockerRunArgs, imageName) @@ -877,7 +868,6 @@ func init() { runCmd.Flags().StringVar(&othPtr, "other", "", "add the following string to 'run' command.") runCmd.Flags().StringVar(&devRMWPtr, "device-rmw", "", "add rmw rules to the following devices (as stated in https://stackoverflow.com/a/62758958). Format : ;") runCmd.Flags().StringVar(&devAccPtr, "device-access", "", "mount the following devices to container (through --device option). Format : ;") - runCmd.Flags().BoolVar(&noSetupSudoPtr, "no-setup-sudo", false, "install inside containers various basic packages, such as apt-utils, sudo, tzdata, vim, or bash-completion.") runCmd.Flags().StringVar(&tempDirPtr, "temp-dir", "", "temporary directory to use for dogi (default: $TMPDIR or /tmp, through empty command). Can be modified if there are access issues with this particular folder.") runCmd.Flags().BoolVar(&noPIDIPCHostPtr, "no-pid-ipc-host", true, "don't launch with --pid=host --ipc=host.") From 62def9f226fa6e0ec0bd886e470231c6d2646097 Mon Sep 17 00:00:00 2001 From: Nicolas Torres Date: Thu, 15 Jan 2026 23:31:37 +0100 Subject: [PATCH 19/21] default to --pid=host --ipc=host and add --no-pid-ipc-host --- cmd/run.go | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/cmd/run.go b/cmd/run.go index 391708e..bfc0c67 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -543,8 +543,12 @@ Examples: bashCmdPath, err := exec.LookPath("bash") check(err) + // if tempdir is not provided, use OS default + if tempDirPtr == "" { + tempDirPtr = os.TempDir() + } + // create xauth magic cookie file - //xauthfile, err := os.CreateTemp("", fmt.Sprintf(".%s*.xauth", appname)) xauthfile, err := os.CreateTemp(tempDirPtr, fmt.Sprintf(".%s*.xauth", appname)) check(err) @@ -575,10 +579,6 @@ Examples: logger.Printf("workdir: %s\n", workDirPtr) mountStrs := []string{fmt.Sprintf("--volume=%s:%s", workDirPtr, workDirPtr)} - //cidFile := fmt.Sprintf("%s/.%s%v.cid", os.TempDir(), appname, rand.Int63()) - if tempDirPtr == "" { - tempDirPtr = os.TempDir() - } cidFile := fmt.Sprintf("%s/.%s%v.cid", tempDirPtr, appname, rand.Int63()) mountStrs = append(mountStrs, fmt.Sprintf("--cidfile=%s", cidFile)) mountStrs = append(mountStrs, fmt.Sprintf("--volume=%s:%s", cidFile, cidFileContainer)) @@ -637,12 +637,13 @@ Examples: if !noNethostPtr { logger.Println("adding --network=host") dockerRunArgs = append(dockerRunArgs, "--network=host") - if noPIDIPCHostPtr { - // useful for https://github.com/eProsima/Fast-DDS/issues/2956 - logger.Println("add --pid=host --ipc=host, to disable use --no-pid-ipc-host") - dockerRunArgs = append(dockerRunArgs, "--pid=host") - dockerRunArgs = append(dockerRunArgs, "--ipc=host") - } + } + + if !noPIDIPCHostPtr { + // useful for https://github.com/eProsima/Fast-DDS/issues/2956 + logger.Println("add --pid=host --ipc=host, to disable use --no-pid-ipc-host") + dockerRunArgs = append(dockerRunArgs, "--pid=host") + dockerRunArgs = append(dockerRunArgs, "--ipc=host") } if privilegedPtr { @@ -869,6 +870,6 @@ func init() { runCmd.Flags().StringVar(&devRMWPtr, "device-rmw", "", "add rmw rules to the following devices (as stated in https://stackoverflow.com/a/62758958). Format : ;") runCmd.Flags().StringVar(&devAccPtr, "device-access", "", "mount the following devices to container (through --device option). Format : ;") runCmd.Flags().StringVar(&tempDirPtr, "temp-dir", "", "temporary directory to use for dogi (default: $TMPDIR or /tmp, through empty command). Can be modified if there are access issues with this particular folder.") - runCmd.Flags().BoolVar(&noPIDIPCHostPtr, "no-pid-ipc-host", true, "don't launch with --pid=host --ipc=host.") + runCmd.Flags().BoolVar(&noPIDIPCHostPtr, "no-pid-ipc-host", false, "don't launch with --pid=host --ipc=host.") } From fd28ed511d494deebaafd1bbfccd5eb820c6a302 Mon Sep 17 00:00:00 2001 From: Nicolas Torres Date: Thu, 15 Jan 2026 23:33:06 +0100 Subject: [PATCH 20/21] remove --other, redundant with usage dogi run -- arg1 arg2 --- cmd/root.go | 1 - cmd/run.go | 7 ------- 2 files changed, 8 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 7fb8174..aebeb35 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -121,7 +121,6 @@ var ( noPIDIPCHostPtr bool workDirPtr string contNamePtr string - othPtr string devAccPtr string devRMWPtr string tempDirPtr string diff --git a/cmd/run.go b/cmd/run.go index bfc0c67..017ec7b 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -806,12 +806,6 @@ Examples: entrypoint = merge([]string{"bash", createUserScriptPath}, execCommand) } - if othPtr != "" { - // add final custom commands. - outStr := strings.Split(othPtr, " ") - dockerRunArgs = append(dockerRunArgs, outStr...) - } - dockerRunArgs = append(dockerRunArgs, imageName) // run command end // ******************************************************** @@ -866,7 +860,6 @@ func init() { runCmd.Flags().BoolVar(&noRMPtr, "no-rm", false, "don't launch with --rm (container will exist after exiting)") runCmd.Flags().BoolVar(&noUSBPtr, "no-usb", false, "don't mount usb devices") runCmd.Flags().BoolVar(&noNethostPtr, "no-nethost", false, "don't launch with --network=host") - runCmd.Flags().StringVar(&othPtr, "other", "", "add the following string to 'run' command.") runCmd.Flags().StringVar(&devRMWPtr, "device-rmw", "", "add rmw rules to the following devices (as stated in https://stackoverflow.com/a/62758958). Format : ;") runCmd.Flags().StringVar(&devAccPtr, "device-access", "", "mount the following devices to container (through --device option). Format : ;") runCmd.Flags().StringVar(&tempDirPtr, "temp-dir", "", "temporary directory to use for dogi (default: $TMPDIR or /tmp, through empty command). Can be modified if there are access issues with this particular folder.") From 6840e4cd826e090b49b422b6cd1f11b4b09dfe1d Mon Sep 17 00:00:00 2001 From: Nicolas Torres Date: Fri, 16 Jan 2026 18:10:21 +0100 Subject: [PATCH 21/21] update deps --- go.mod | 18 +++++++++--------- go.sum | 51 +++++++++++++++++++++------------------------------ 2 files changed, 30 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index 2382e09..bb01965 100644 --- a/go.mod +++ b/go.mod @@ -1,20 +1,20 @@ module github.com/ntorresalberto/dogi -go 1.17 +go 1.25.6 require ( - github.com/AlecAivazis/survey/v2 v2.3.6 - github.com/spf13/cobra v1.7.0 + github.com/AlecAivazis/survey/v2 v2.3.7 + github.com/spf13/cobra v1.10.2 ) require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect - github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/term v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect + github.com/spf13/pflag v1.0.10 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/term v0.39.0 // indirect + golang.org/x/text v0.33.0 // indirect ) diff --git a/go.sum b/go.sum index 9d53d87..abd4b9d 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ -github.com/AlecAivazis/survey/v2 v2.3.6 h1:NvTuVHISgTHEHeBFqt6BHOe4Ny/NwGZr7w+F8S9ziyw= -github.com/AlecAivazis/survey/v2 v2.3.6/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI= +github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= +github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -15,67 +15,58 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=