From ec6201c8eb2402919b15b29cfc4f37dd807ed0e7 Mon Sep 17 00:00:00 2001 From: Alexey Romanov Date: Fri, 26 Mar 2021 16:16:17 +0300 Subject: [PATCH] USER instruction in Dockerfile uses UID and GID numbers (#514) It is possible to run an image generated with the ``cartridge pack docker`` command in an unprivileged Kubernetes container. It became possible, because tarantool user now always has ``UID = 1200`` and ``GID = 1200``. Closes #481 --- CHANGELOG.md | 10 ++++- cli/pack/docker.go | 10 +++++ cli/project/dockerfiles.go | 28 +++++++++----- cli/project/dockerfiles_test.go | 45 +++++++++++++++-------- test/integration/pack/test_pack_docker.py | 17 +++++++++ 5 files changed, 82 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11b7aa690..76bd904b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Fixed + +- It is possible to run an image generated with the ``cartridge pack docker`` + command in an unprivileged Kubernetes container. It became possible, because + tarantool user now always has ``UID = 1200`` and ``GID = 1200``. + ## [2.7.2] - 2021-03-24 ### Changed @@ -15,7 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Updated `metrics` to `0.7.1` in application template - Updated `cartridge-cli-extensions` to `1.1.1` in application template -## Added +### Added - Variables ``TARANTOOL_WORKDIR``, ``TARANTOOL_PID_FILE`` and ``TARANTOOL_CONSOLE_SOCK`` can be customized when packing in docker via @@ -28,7 +34,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Updated `cartridge` to `2.5.0` in application template -## Fixed +### Fixed - Added interruption of an incomplete expression when pressing ``Ctrl-C`` in ``cartridge enter`` command. diff --git a/cli/pack/docker.go b/cli/pack/docker.go index 5212e90ea..9975dbb75 100644 --- a/cli/pack/docker.go +++ b/cli/pack/docker.go @@ -12,6 +12,14 @@ import ( "github.com/tarantool/cartridge-cli/cli/project" ) +// We have to set constant UID and GID for Tarantool +// user (see cli/project/dockerfiles.go for details). +// The number 1200 was chosen at random. +const ( + tarantoolUID = 1200 + tarantoolGID = 1200 +) + func packDocker(ctx *context.Ctx) error { if err := docker.CheckMinServerVersion(); err != nil { return err @@ -36,6 +44,8 @@ func packDocker(ctx *context.Ctx) error { "Name": ctx.Project.Name, "TmpFilesConf": tmpFilesConfContent, "AppDir": ctx.Running.AppDir, + "TarantoolUID": tarantoolUID, + "TarantoolGID": tarantoolGID, "AppEntrypointPath": project.GetAppEntrypointPath(ctx), "WorkDir": project.GetInstanceWorkDir(ctx, "${TARANTOOL_INSTANCE_NAME}"), "PidFile": project.GetInstancePidFile(ctx, "${TARANTOOL_INSTANCE_NAME}"), diff --git a/cli/project/dockerfiles.go b/cli/project/dockerfiles.go index e1f3e46e5..73e4e4fc4 100644 --- a/cli/project/dockerfiles.go +++ b/cli/project/dockerfiles.go @@ -80,9 +80,9 @@ func GetRuntimeImageDockerfileTemplate(ctx *context.Ctx) (*templates.FileTemplat return nil, fmt.Errorf("Failed to get install Tarantool Dockerfile layers: %s", err) } - dockerfileParts = append(dockerfileParts, installTarantoolLayers) + dockerfileParts = append(dockerfileParts, createTarantoolUser, installTarantoolLayers) } else { - dockerfileParts = append(dockerfileParts, createUserLayers) + dockerfileParts = append(dockerfileParts, createTarantoolUser, createTarantoolDirectories) } // Set runtime user, env and copy application code @@ -190,26 +190,34 @@ const ( defaultBaseLayers = "FROM centos:7\n" installBuildPackagesLayers = `### Install packages required for build RUN yum install -y git-core gcc gcc-c++ make cmake unzip +` + // We have to set USER instruction in the form of + // (see https://github.com/tarantool/cartridge-cli/issues/481). + // Since we cannot find out the already set UID and GID for the tarantool + // user using command shell (see https://github.com/moby/moby/issues/29110), + // we recreate the user and the tarantool group with a constant UID and GID value. + + createTarantoolUser = `### Create Tarantool user +RUN groupadd -r -g {{ .TarantoolGID }} tarantool \ + && useradd -M -N -l -u {{ .TarantoolUID }} -g tarantool -r -d /var/lib/tarantool -s /sbin/nologin \ + -c "Tarantool Server" tarantool ` // Some versions of Docker have a bug with consumes all disk space. // In order to fix it, we have to specify the -l flag for the `adduser` command. // More details: https://github.com/docker/for-mac/issues/2038#issuecomment-328059910 - createUserLayers = `### Create Tarantool user and directories -RUN groupadd -r tarantool \ - && useradd -M -N -l -g tarantool -r -d /var/lib/tarantool -s /sbin/nologin \ - -c "Tarantool Server" tarantool \ - && mkdir -p /var/lib/tarantool/ --mode 755 \ + createTarantoolDirectories = `### Create directories +RUN mkdir -p /var/lib/tarantool/ --mode 755 \ && chown tarantool:tarantool /var/lib/tarantool \ && mkdir -p /var/run/tarantool/ --mode 755 \ - && chown tarantool:tarantool /var/run/tarantool + && chown tarantool:tarantool /var/run/tarantool ` - prepareRuntimeLayers = `### Prepare for runtime RUN echo '{{ .TmpFilesConf }}' > /usr/lib/tmpfiles.d/{{ .Name }}.conf \ && chmod 644 /usr/lib/tmpfiles.d/{{ .Name }}.conf -USER tarantool:tarantool +USER {{ .TarantoolUID }}:{{ .TarantoolGID }} + ENV CARTRIDGE_RUN_DIR=/var/run/tarantool ENV CARTRIDGE_DATA_DIR=/var/lib/tarantool ENV TARANTOOL_INSTANCE_NAME=default diff --git a/cli/project/dockerfiles_test.go b/cli/project/dockerfiles_test.go index d9d7ff0e9..563dcaa95 100644 --- a/cli/project/dockerfiles_test.go +++ b/cli/project/dockerfiles_test.go @@ -307,20 +307,23 @@ func TestGetRuntimeImageDockerfileTemplateEnterprise(t *testing.T) { expLayers = `FROM centos:7 -### Create Tarantool user and directories -RUN groupadd -r tarantool \ - && useradd -M -N -l -g tarantool -r -d /var/lib/tarantool -s /sbin/nologin \ - -c "Tarantool Server" tarantool \ - && mkdir -p /var/lib/tarantool/ --mode 755 \ +### Create Tarantool user +RUN groupadd -r -g {{ .TarantoolGID }} tarantool \ + && useradd -M -N -l -u {{ .TarantoolUID }} -g tarantool -r -d /var/lib/tarantool -s /sbin/nologin \ + -c "Tarantool Server" tarantool + +### Create directories +RUN mkdir -p /var/lib/tarantool/ --mode 755 \ && chown tarantool:tarantool /var/lib/tarantool \ && mkdir -p /var/run/tarantool/ --mode 755 \ - && chown tarantool:tarantool /var/run/tarantool + && chown tarantool:tarantool /var/run/tarantool ### Prepare for runtime RUN echo '{{ .TmpFilesConf }}' > /usr/lib/tmpfiles.d/{{ .Name }}.conf \ && chmod 644 /usr/lib/tmpfiles.d/{{ .Name }}.conf -USER tarantool:tarantool +USER {{ .TarantoolUID }}:{{ .TarantoolGID }} + ENV CARTRIDGE_RUN_DIR=/var/run/tarantool ENV CARTRIDGE_DATA_DIR=/var/lib/tarantool ENV TARANTOOL_INSTANCE_NAME=default @@ -356,20 +359,23 @@ RUN yum install -y zip expLayers = `FROM centos:7 RUN yum install -y zip -### Create Tarantool user and directories -RUN groupadd -r tarantool \ - && useradd -M -N -l -g tarantool -r -d /var/lib/tarantool -s /sbin/nologin \ - -c "Tarantool Server" tarantool \ - && mkdir -p /var/lib/tarantool/ --mode 755 \ +### Create Tarantool user +RUN groupadd -r -g {{ .TarantoolGID }} tarantool \ + && useradd -M -N -l -u {{ .TarantoolUID }} -g tarantool -r -d /var/lib/tarantool -s /sbin/nologin \ + -c "Tarantool Server" tarantool + +### Create directories +RUN mkdir -p /var/lib/tarantool/ --mode 755 \ && chown tarantool:tarantool /var/lib/tarantool \ && mkdir -p /var/run/tarantool/ --mode 755 \ - && chown tarantool:tarantool /var/run/tarantool + && chown tarantool:tarantool /var/run/tarantool ### Prepare for runtime RUN echo '{{ .TmpFilesConf }}' > /usr/lib/tmpfiles.d/{{ .Name }}.conf \ && chmod 644 /usr/lib/tmpfiles.d/{{ .Name }}.conf -USER tarantool:tarantool +USER {{ .TarantoolUID }}:{{ .TarantoolGID }} + ENV CARTRIDGE_RUN_DIR=/var/run/tarantool ENV CARTRIDGE_DATA_DIR=/var/lib/tarantool ENV TARANTOOL_INSTANCE_NAME=default @@ -416,6 +422,11 @@ func TestGetRuntimeImageDockerfileTemplateOpensource(t *testing.T) { expLayers = `FROM centos:7 +### Create Tarantool user +RUN groupadd -r -g {{ .TarantoolGID }} tarantool \ + && useradd -M -N -l -u {{ .TarantoolUID }} -g tarantool -r -d /var/lib/tarantool -s /sbin/nologin \ + -c "Tarantool Server" tarantool + ### Install opensource Tarantool RUN curl -L https://tarantool.io/installer.sh | VER=1.10 bash \ && yum -y install tarantool-devel @@ -424,7 +435,8 @@ RUN curl -L https://tarantool.io/installer.sh | VER=1.10 bash \ RUN echo '{{ .TmpFilesConf }}' > /usr/lib/tmpfiles.d/{{ .Name }}.conf \ && chmod 644 /usr/lib/tmpfiles.d/{{ .Name }}.conf -USER tarantool:tarantool +USER {{ .TarantoolUID }}:{{ .TarantoolGID }} + ENV CARTRIDGE_RUN_DIR=/var/run/tarantool ENV CARTRIDGE_DATA_DIR=/var/lib/tarantool ENV TARANTOOL_INSTANCE_NAME=default @@ -465,7 +477,8 @@ RUN curl -L https://tarantool.io/installer.sh | VER=1.10 bash \ RUN echo '{{ .TmpFilesConf }}' > /usr/lib/tmpfiles.d/{{ .Name }}.conf \ && chmod 644 /usr/lib/tmpfiles.d/{{ .Name }}.conf -USER tarantool:tarantool +USER {{ .TarantoolUID }}:{{ .TarantoolGID }} + ENV CARTRIDGE_RUN_DIR=/var/run/tarantool ENV CARTRIDGE_DATA_DIR=/var/lib/tarantool ENV TARANTOOL_INSTANCE_NAME=default diff --git a/test/integration/pack/test_pack_docker.py b/test/integration/pack/test_pack_docker.py index 2ceb1d229..01eef88cb 100644 --- a/test/integration/pack/test_pack_docker.py +++ b/test/integration/pack/test_pack_docker.py @@ -309,3 +309,20 @@ def test_customized_data_and_run_dir(docker_image_print_environment, docker_clie container_message = f"{console_sock_path}\n{workdir_path}\n{pidfile_path}\n" wait_for_container_start(container, time.time(), message=container_message) + + +def test_tarantool_uid_and_gid(docker_image, docker_client): + image_name = docker_image.name + docker_client.containers.create(docker_image.name) + + command = 'whoami' + output = run_command_on_image(docker_client, image_name, command) + assert output == 'tarantool' + + command = 'id -u tarantool' + output = run_command_on_image(docker_client, image_name, command) + assert output == '1200' + + command = 'id -g tarantool' + output = run_command_on_image(docker_client, image_name, command) + assert output == '1200'