From e65a286a6fead54f03d3357da3092622f819edd8 Mon Sep 17 00:00:00 2001 From: XV25 Date: Tue, 4 Feb 2025 14:41:10 +0100 Subject: [PATCH 01/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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 b37e51c8824a78ba873cc3f226e8a1c8317ec553 Mon Sep 17 00:00:00 2001 From: XV25 <37617370+XV25@users.noreply.github.com> Date: Wed, 14 Jan 2026 14:01:31 +0100 Subject: [PATCH 14/14] Update README.md * Corrected possible install procedures * Added example for camera access --- README.md | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0c4966a..b215855 100644 --- a/README.md +++ b/README.md @@ -28,10 +28,21 @@ Bug : Error response from daemon: unknown or invalid runtime name: nvidia ## Quickstart +First, do : + +``` +## To install this fork +export DOGI_INSTALL_GITHUB="XV25" +## To install the original repo +export DOGI_INSTALL_GITHUB="ntorresalberto" +``` + +Then : + ```bash # install binary mkdir -pv ~/go/bin -wget -qO- https://github.com/ntorresalberto/dogi/releases/download/rolling/dogi-rolling-linux-amd64.tar.gz | tar xvz -C ~/go/bin +wget -qO- https://github.com/$DOGI_INSTALL_GITHUB/dogi/releases/download/rolling/dogi-rolling-linux-amd64.tar.gz | tar xvz -C ~/go/bin # add bash autocompletion echo 'source <(dogi completion bash)' >> ~/.bashrc @@ -104,6 +115,13 @@ Some [optional setup steps](#optional-setup-steps) might be required. dogi run ubuntu --no-user -- bash -c "apt install -y mesa-utils && glxgears" # as root ``` +- Add access to a webcam (ex : /dev/video0) (after having given access, for example, through ``` sudo usermod -aG video $USER```) : + +```bash + dogi run ubuntu --device-access "/dev/video0" +``` + + - Delete unused and/or dangling containers, images and volumes ```bash @@ -145,8 +163,19 @@ You should find **dogi** useful if you: ### Installing from source +First, do : + +``` +## To install this fork +export DOGI_INSTALL_GITHUB="XV25" +## To install the original repo +export DOGI_INSTALL_GITHUB="ntorresalberto" +``` + +Then : + ```bash -git clone https://github.com/ntorresalberto/dogi.git +git clone https://github.com/$DOGI_INSTALL_GITHUB/dogi.git cd dogi make install dogi -v # test it!