Switch to root account in Docker

Usually, a docker container has a way to easily switch to root account.

It can be as easy as 'su root' or even root by default when you run a shell such as 'bash' within it.

However, sometimes, it's not that easy. You need to work hard for it.

My issues where the following:

  • su command won't work as it's just a symlink to busybox:
1~ $ ls -l `which su`
2lrwxrwxrwx    1 root     root            12 Oct 21  2020 /bin/su -> /bin/busybox
  • No known root password or sudo is not possible

Solution

  1. su problem - create a copy of /bin/busybox to somewhere you can modify permissions.
1~$ cp /bin/busybox /var/www/frontend/su       ### you're inside the container here
2~$ exit                                       ### go out to host OS (e.g. Ubuntu WSL)
3~$ pwd
4/home/ubuntu/work/src/frontend
5~$ sudo chown root:root su
6~$ chmod u+s su

Inside the container, you should see it as follows:

1-rwsr-xr-x    1 root     root        841288 Mar 22 11:12 su
  1. create a fake /etc/passwd file
1echo "node:x:$(id -u):$(id -g)::/home/node:/bin/sh" > /tmp/fake-passwd
2echo "root:x:$0:0::/:bin/sh"                        >> /tmp/fake-passwd 
  1. Add the password changer to Dockerfile so you know what password to use when you finally su:
1RUN echo 'root:Docker!' | chpasswd
  1. Mount the /tmp/fake-passwd to docker-compose service or docker. In my case I have docker-compose so I just added it to the corresponding service volumes section
 1  node:
 2    user: 1000:1000
 3    build:
 4      context: .
 5      dockerfile: "./docker/node/${ENVIRONMENT}.Dockerfile"
 6    image: ${PROJECT_NAME}_node:${ENVIRONMENT}
 7    container_name: ${PROJECT_NAME}_node
 8    working_dir: /var/www/frontend
 9    volumes:
10      - "/var/www/frontend/node_modules"
11      - /tmp/fake-passwd:/etc/passwd
12    volumes_from:
13      - data
14    environment:
15      - NODE_ENV=development
16      - CHOKIDAR_USEPOLLING=true
17    ports:
18      - "3000:3000"
...
  1. Then rebuild the corresponding container (in my case, it was node):
1docker-compose build node 
  1. Now shell into the container and su using created version, and you know the password to root. See #3 above
1~$ docker-compose exec node sh     ## Shell to container
2~$ pwd
3/var/www/frontend
4~$ ./su 
5Password:                          ## Input the password in #3 above
6/var/www/frontend #                ## See how the prompt changes to # which means, you're now the root user.
  1. Overwrite the /bin/su with the one that works. Check that the sticky-bit ('s' in owner permission) still exist.
1/var/www/frontend # cp su /bin/su
2/var/www/frontend # ls -l /bin/su
3-rwsr-xr-x    1 root     root        841288 Mar 23 02:21 /bin/su
4/var/www/frontend # ls -l su
5-rwsr-xr-x    1 root     root        841288 Mar 22 11:12 su
6/var/www/frontend # sha256sum /bin/su
7d62b5272e28473938cd6b8be12cc6260195e635968c1b02397b9e851702ccedb  /bin/su
8/var/www/frontend # sha256sum su
9d62b5272e28473938cd6b8be12cc6260195e635968c1b02397b9e851702ccedb  su
...

You may delete after the temporary su created in step #1 after testing that it works.

Enjoy!

References: