Run Docker as rootless mode - docker

I am trying to run a docker as a rootless mode in ubuntu VM.
I am provisioning the VM using the terraform script.
I am using the terraform run module to execute commands and prerequisites.
but when I have added docker as rootless mode commands in this run module those scripts are not executing even though I switch the new user.
Below are the commands I need to execute as another user in the terraform run module.
sudo apt-get install -y uidmap
curl -fsSL https://get.docker.com/rootless | sh
export DOCKER_HOST=unix:///run/user/1000/docker.sock
systemctl --user status docker
I am getting an error as Refusing to install rootless Docker as the root user
My goal is to automate this using a terraform run module.
should any could help to solve this issue or is there any other workaround for this.
Thanks in Advance.
I have tried with switch user and execute but still, these commands are not executing.
sudo apt-get install -y uidmap
curl -fsSL https://get.docker.com/rootless | sh
export DOCKER_HOST=unix:///run/user/1000/docker.sock
systemctl --user status docker
I would like to automate this using a terraform run module or any other way but the only thing is this should be executed once VM is provision.

Read the script https://get.docker.com/rootless where it says "This script should be run with an unprivileged user and install/setup Docker under $HOME/bin/"
If you do still want to install it then you just need to learn how to read shell scripts as there is this part in the script:
# User verification: deny running as root (unless forced?)
if [ "$(id -u)" = "0" ] && [ -z "$FORCE_ROOTLESS_INSTALL" ]; then
>&2 echo "Refusing to install rootless Docker as the root user"; exit 1
fi

Related

Rootless VS Code (dockerized)?

Is there any method to install VS Code in a docker container as a web-based editor that can be run in a rootless mode (no sudo in container entrypoint scripts etc.)?
E.g. to run it in this scenario:
docker run -u 12345 --cap-drop=all repo/rootless-vscode
Here is an example of how it can be done with code-server.
Note that it needs root permissions to install the server, but runs it as newuser.
FROM ubuntu:22.04
RUN apt update
RUN apt install -y sudo curl
RUN curl -fsSL https://code-server.dev/install.sh | sh
RUN useradd -ms /bin/bash newuser
USER newuser
CMD [ "code-server", "--bind-addr", "0.0.0.0:8080" ]
For a more complete example, check out their code-server CI release Dockerfile.

Facing issue while setup bind9 in Dockerfile

I am new in docker, I want to build an image with Ubuntu 20.04 and bind9 service installation.
below is my code of docker file
FROM ubuntu:20.04
ENV TZ=Asia
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get update && apt-get install -y \
apt-utils \
systemctl \
bind9
RUN /usr/sbin/named -g -c /etc/bind/named.conf -u bind
RUN systemctl restart bind9
I am getting an error like below
ERROR:systemctl:Unit bind9.service could not be found.
Can anyone help me, after installation of Bind9, why I am getting an error with above command?
Error comes with Docker only, if I run same command in Host environment which is Ubuntu 20.04 then it works fine.
You generally cannot use service management commands (like service or systemctl, etc) in a container, because there is no service manager running.
Additionally, even if there were a service manager running, it wouldn't make any sense to interact with it in a RUN command: these commands are part of the image build process, and there are no persistent services running at this point. A RUN command runs in an isolated environment that is completely torn down when the RUN command completes.
If you want bind to start when you run a container using your image, you would need to place the appropriate bind command line into the CMD option. For example, the official bind9 image includes:
CMD ["/usr/sbin/named", "-g", "-c", "/etc/bind/named.conf", "-u", "bind"]
(See the Dockerfile for details)

apt-get update Rootless Docker

Installing Rootful Docker on my Raspberry Pi updates the sources and one can configure unattended-upgrades to update Docker automatically by looking at sudo apt-cache policy.
However, Rootless Docker doesn't. So is there a way to upgrade Rootless Docker ?
In other words:
With Rootful Docker, sudo apt-get update && sudo apt-get -y upgrade on the host could upgrade the Docker installation. I would like to be able to do something similar with Rootless Docker.
Is it possible ?
To clarify: I am not trying to update the containers, but Docker itself.
Thanks in advance for any help you can provide :)
As far as I know, there isn't special rootless package for Debian so you can't do that with package manager. Some rootless binaries are bit different, missing SETUID bits and some other file capabilities.
However, you can try to run rootless installation script again, if that updates your binaries.
curl -fsSL https://get.docker.com/rootless | sh
These are also available here as rootless-extras , but it requires manual extraction:
I also found no official way to update a docker-rootless installation.
So here is how i update docker-rootless. its a bit experimental, but it works for me. maybe it needs some more tests to make it more robust and ready to be usable in a script or crontab:
# UPDATE DOCKER-ROOTLESS (as user which docker-rootless runs with):
# stop your docker daemon ... (takes long time for me and doesn't finish problerly)
systemctl --user stop docker.service
# maybe you have to kill it because it hangs up and doesn't finish proberly
CTRL+C
# check that docker.service isn't running (important !!!)
systemctl --user status docker.service
# Active: inactive (dead)
# OR:
# Active: failed (Result: exit-code)
# download docker-rootless installation script
wget https://get.docker.com/rootless -O rootless.sh
# set environment variables (used by rootless.sh script)
SKIP_IPTABLES=1
FORCE_ROOTLESS_INSTALL=1
# remove "Already installed verification" check from script
sed -i s#\-x\ \"\$BIN/\$DAEMON\"#\!\ \-x\ \"\$BIN/\$DAEMON\"#g rootless.sh
# make rootles.sh executable
chmod +x rootless.sh
# run rootless.sh
./rootless.sh
# kill installation script, because it starts docker.service and keeps running
CTRL+C
# finally setcap cap_net_bind_service (to bind ports less than 1024)
# replace 'docker' with the username you are logged in with
sudo setcap cap_net_bind_service=ep /home/docker/bin/rootlesskit
# DONE (docker should now be updated)
docker --version
# Docker version 20.10.6, build 370c289
# UPDATE DOCKER-COMPOSE (with sudo or root):
# get and save latest docker-compose version
DOCKER_COMPOSE_VERSION=$(curl -L "https://docs.docker.com/compose/install/" | grep -o -P '(?<=https://github.com/docker/compose/releases/download/).*(?=/docker-compose)' | head -n1)
# download docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# make it executable
sudo chmod +x /usr/local/bin/docker-compose
# link it to /usr/bin
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# DONE (docker-compose should now be updated)
docker-compose --version
# docker-compose version 1.29.1, build c34c88b2
# remove docker-rootless script
rm rootless.sh
# maybe you should reboot your host once!
sudo reboot

Can't add jenkins-job-builder in jenkins docker image

I'm new in docker. I want to create a docker container with Newman, Jenkins, Jenkins-job-builder. Please help me.
I built a docker image which bases on official Jenkins image https://hub.docker.com/r/jenkins/jenkins.
I used DockerFile. The build was successful, Jenkins app also runs successfully.
After running Jenkins I opened container as root
docker exec -u 0 -it jenkins bash and tryed to add new job with jenkins-job-builder
jenkins-jobs --conf ./jenkins_jobs.ini update ./jobs.yaml
but I got bash: jenkins-jobs: command not found
There is my Dockerfile
FROM jenkins/jenkins
USER root
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash
RUN apt-get -y install nodejs
RUN npm install -g newman
RUN curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
RUN python get-pip.py
RUN pip install --user jenkins-job-builder
USER jenkins
When building your image, you get some warnings. Especially this one is interesting:
WARNING: The script jenkins-jobs is installed in '/root/.local/bin' which is not on PATH.
Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Simply remove the --user flag from RUN pip install --user jenkins-job-builder and you're fine.

Unable to run systemd inside docker which is being run inside jenkins

I'm trying to get Jenkins to run Docker that runs SystemD.
So far I've been able to run systemd inside docker locally without Jenkins. Here are the steps to run it locally without jenkins:
# pull unop/fedora-systemd and create and run the container for it
sudo docker run --cap-add=SYS_ADMIN -e container=docker --tmpfs /run --tmpfs /tmp -v /sys/fs/cgroup:/sys/fs/cgroup:ro -t -i unop/fedora-systemd
# on a different terminal window, I can:
# get the container id of the "unop/fedora-systemd" image
sudo docker ps
# then exec bash on it
sudo docker container exec -t -i a98aa2bcd19e bash # where a98aa2bcd19e is the container id found above
# once inside the container, I can run systemd without any problems. examples:
systemctl status
systemctl start dbus.service
systemctl status dbus.service
The above works locally and I am able to run systemd inside the docker container.
The problem I get is when I try the same thing, but inside Jenkins.
I've tried to tweak Jenkinsfile several times, but not of my previous tries seemed to work. I always get an error when running under Jenkins similar to this:
+ systemctl status
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
This is my latest Jenkinsfile that I've tried
pipeline {
agent {
docker {
image 'unop/fedora-systemd'
args '--cap-add=SYS_ADMIN -e container=docker --tmpfs /run --tmpfs /tmp -v /sys/fs/cgroup:/sys/fs/cgroup:ro -t -i'
}
}
stages {
stage('test') {
steps {
sh "echo hello world"
sh "systemctl status"
sh "systemctl start dbus.service"
sh "systemctl dbus.service"
}
}
}
}
On previous iterations of the Jenkinsfile, I've tried to replace -cap-add=SYS_ADMIN -e container=docker for --privileged, but that didn't help, I still got the same errors
Anyone have an idea of how can I get this to work? Why does the above work locally, but not on Jenkins? what am I missing here?
Note: Jenkins version: 2.150.2 and this is the Dockerfile used by unop/fedora-systemd
FROM fedora:rawhide
MAINTAINER http://fedoraproject.org/wiki/Cloud
ENV container docker
RUN dnf -y update && dnf clean all
RUN dnf -y install systemd && dnf clean all && \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup", "/tmp", "/run" ]
CMD ["/usr/sbin/init"]
PS: I've seen a related question, but what they were asking is different
I did not know about the related question. Let me point out again that you do not need to run a systemd daemon in a systemd controlled container if it is just about running multiple services in it. Simply overwrite /usr/bin/systemctl with the docker-systemctl-replacement script. Then go to register it with CMD ["/usr/bin/systemctl"] as the init process of the container.
That's it. Now you can run any systemctl-start process from the operating system. It works to the extent that even provisioning with ansible/puppet scripts have no problem at all. An specficially, I am using that to provision Jenkins images with the operating system that the developers like to have as a basis. No priviledged mode required.
You may try an image that has Fedora with System D already active with this command:
docker run -d --name systemd-fedora --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro jrei/systemd-fedora
Then you just need to run:
docker exec -it systemd-fedora /bin/bash
and there you can just install, start and restart any service you need.

Resources