#TIL : Run container processes as non-root user

As default, docker runs your container as root user (uid=0). Although docker isolates your filesystem to protect docker host, but running processes as root is redundant and increasing attacking surface. Even it can make its written files having root owner, which can mess your docker-host filesystem permission.

This is example that show docker runs as root

1
$ docker run --rm alpine sleep 30

and open another terminal to check this

1
2
3
4
$ ps xau | grep 'sleep'
khanhic+ 15552 0.5 0.4 1264452 49280 pts/1 Sl+ 17:37 0:00 docker run --rm alpine:3.9 sleep 30
root 15610 0.6 0.0 1520 4 ? Ss 17:37 0:00 sleep 30
khanhic+ 15876 0.0 0.0 23076 1024 pts/2 S+ 17:37 0:00 grep --color=auto sleep

You can see that the process sleep 30 is running as root with pid = 15610


To control which user docker container runs as, you can use the --user [userid]:[groupid] argument

Example

1
$ docker run --rm --user 1000:1000 alpine sleep 30

Then you will get this result

1
2
3
4
$ ps xau | grep 'sleep'
khanhic+ 16275 2.0 0.4 1411916 50124 pts/1 Sl+ 17:41 0:00 docker run --rm --user 1000:1000 alpine:3.9 sleep 30
khanhic+ 16336 1.5 0.0 1520 4 ? Ss 17:41 0:00 sleep 30
khanhic+ 16403 0.0 0.0 23076 984 pts/2 S+ 17:41 0:00 grep --color=auto sleep

TIP : you can set a environment variable by add this line to ~/.bash_profile or ~/.bashrc

1
export DOCKER_UID="$(id -u ${USER}):$(id -g ${USER})"`

then use docker command like docker run --user $DOCKER_UID ....

#TIL : Can not run downloaded binary inside alpine linux because of missing shared libs

Alpine linux becomes the most base image for docker images because it’s lightweight and handful package manager apk. Sometimes, you create an image that downloads the binary file but can not execute it. It shows something like this:

1
/entrypoint.sh: line ***: [your binary]: not found

The problem is your binary built within shared libraries, so it can’t run without shared libraries dependencies. To findout which libraries is missing, use this

1
$ ldd [your binary path]

This is sample result

1
2
3
4
5
6
7
8
/usr/local/bin # ldd hugo
/lib64/ld-linux-x86-64.so.2 (0x7fa852f2a000)
libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7fa852f2a000)
Error loading shared library libstdc++.so.6: No such file or directory (needed by hugo)
libdl.so.2 => /lib64/ld-linux-x86-64.so.2 (0x7fa852f2a000)
libm.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7fa852f2a000)
Error loading shared library libgcc_s.so.1: No such file or directory (needed by hugo)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7fa852f2a000)

So we need to install libstdc++ and libc6-compat before run the binary

1
RUN apk add --no-cache libstdc++ libc6-compat

#TIL : SSH to docker host in Docker for Mac

When you need to debug the docker host of your docker server inside macOS. You can connect to its tty screen by

1
$ screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty

Then type ENTER to enter the screen and start debugging docker host.

To disconnect the screen, press “Ctrl + A > Ctrl + " and confirm “yes”.

#TIL : Build lightweight image by using multistage

Docker is great tool to build a pull-n-run application. But sometimes, your image will be large if you build image from a big base image which has heavy compliling toolbox.

Ex:

One-stage build

1
2
3
4
5
FROM golang:1.9.2
WORKDIR /go/src/github.com/khanhicetea/test/
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build .
ENTRYPOINT ["/go/src/github.com/khanhicetea/test/test"]

Multi-stage builds

1
2
3
4
5
6
7
8
FROM golang:1.9.2
WORKDIR /go/src/github.com/khanhicetea/test/
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build .

FROM scratch
COPY --from=0 /go/src/github.com/khanhicetea/test/test .
ENTRYPOINT ["/test"]

So final image will only contains /test excutable file. COPY --from=0 means COPY from build has index 0 in Dockerfile.

#TIL : Reduce init time MySQL docker image

Original MySQL docker image uses a script to generate ssl certificates for service. Sometime we don’t really need it (connect via a docker network link or need a fast enough database service to build a automated test).

We can reduce init time by removing the script from original Docker image

1
2
3
4
FROM mysql:5.7

# Remove mysql_ssl_rsa_setup to ignore setup SSL certs
RUN rm -f /usr/bin/mysql_ssl_rsa_setup

FAST as a FEATURE !!! 🚀

#TIL : Changing channel from alpha to stable will remove ALL DATA

On MacOS, changing Docker channel will remove all data (includes volumes, images, networks and … everything).

Because Docker on Mac using a minimal Linux machine to host docker engine, so changing machine means discarding all old data. So BECAREFUL !

#TIL : Reducing docker image the right way

When building an image, Docker engine commit file system layer on every command (RUN, ADD, COPY). So next time you installing packages from package manager likes apt, yum, pacman, …remember clean their cache in same line.

BAD WAY

1
2
3
4
5
6
7
RUN apt-get update
RUN apt-get install git

# Something here

# End of file
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RIGHT WAY

1
RUN apt-get update && apt-get install -y git zip unzip && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*