-
Notifications
You must be signed in to change notification settings - Fork 443
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement dockerPermissionStrategy #1190
Conversation
d8d8009
to
d3e7c6b
Compare
Thanks for the pull request @eed3si9n . I'll take a deeper look when I have some time. Hopefully this week. |
Fixes sbt#1189 This implements a non-root Docker container that's safer by default and compatible with Red Hat OpenShift. Current `ADD --chown=daemon:daemon opt /opt` nominally implements non-root image, but by giving ownership of the working directory to the `daemon` user, it reduces the safety. Instead we should use `chmod` to default to read-only access unless the build user opts into writable working directory. The challenge is calling `chmod` without incurring the fs layer overhead (sbt#883). [Multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/) can be used to pre-stage the files with desired file permissions. This adds new `dockerPermissionStrategy` setting which decides how file permissions are set for the working directory inside the Docker image generated by sbt-native-packager. The strategies are: - `DockerPermissionStrategy.MultiStage` (default): uses multi-stage Docker build to call chmod ahead of time. - `DockerPermissionStrategy.None`: does not attempt to change the file permissions, and use the host machine's file mode bits. - `DockerPermissionStrategy.Run`: calls `RUN` in the Dockerfile. This has regression on the resulting Docker image file size. - `DockerPermissionStrategy.CopyChown`: calls `COPY --chown` in the Dockerfile. Provided as a backward compatibility. For `MultiStage` and `Run` strategies, `dockerChmodType` is used in addition to call `chmod` during Docker build. - `DockerChmodType.UserGroupReadExecute` (default): chmod -R u=rX,g=rX - `DockerChmodType.UserGroupWriteExecute`: chmod -R u=rwX,g=rwX - `DockerChmodType.SyncGroupToUser`: chmod -R g=u - `DockerChmodType.Custom`: Custom argument provided by the user. Some application will require writing files to the working directory. In that case the setting should be changed as follows: ```scala import com.typesafe.sbt.packager.docker.DockerChmodType dockerChmodType := DockerChmodType.UserGroupWriteExecute ``` During `docker:stage`, Docker package validation is called to check if the selected strategy is compatible with the deteted Docker version. This fixes the current repeatability issue reported as sbt#1187. If the incompatibility is detected, the user is advised to either upgrade their Docker, pick another strategy, or override the `dockerVersion` setting. `daemonGroup` is set to `root` instead of copying the value from the `daemonUser` setting. This matches the semantics of `USER` as well as OpenShift, which uses gid=0.
914c277
to
12b5fcb
Compare
Cool. Let me squash the intermediate commits with failing tests. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome PR @eed3si9n . I really like the approach 😍
Only minor comments. Could you also add the the setting to the docker.rst documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! Thanks for the quick response. I'll trigger a release immediately.
I always use the Squash and merge button from github 😁 |
Documentation in the |
Fixes #1189
This implements a non-root Docker container that's safer by default and compatible with Red Hat OpenShift.
Current
ADD --chown=daemon:daemon opt /opt
andUSER daemon
combination nominally implements non-root image, but by giving ownership of the working directory to thedaemon
user, it reduces the safety.Instead we should use
chmod
to default to read-only access unless the build user opts into writable working directory.The challenge is calling
chmod
without incurring the fs layer overhead (#883).Multi-stage builds can be used to pre-stage the files with desired file permissions.
This adds new
dockerPermissionStrategy
setting which decides how file permissions are set for the working directory inside the Docker image generated by sbt-native-packager. The strategies are:DockerPermissionStrategy.MultiStage
(default): uses multi-stage Docker build to call chmod ahead of time.DockerPermissionStrategy.None
: does not attempt to change the file permissions, and use the host machine's file mode bits.DockerPermissionStrategy.Run
: callsRUN
in the Dockerfile. This has regression on the resulting Docker image file size.DockerPermissionStrategy.CopyChown
: callsCOPY --chown
in the Dockerfile. Provided as a backward compatibility.Working directory is read-only by default
For
MultiStage
andRun
strategies,dockerChmodType
is used in addition to callchmod
during Docker build.DockerChmodType.UserGroupReadExecute
(default): chmod -R u=rX,g=rXDockerChmodType.UserGroupWriteExecute
: chmod -R u=rwX,g=rwXDockerChmodType.SyncGroupToUser
: chmod -R g=uDockerChmodType.Custom
: Custom argument provided by the user.How to opt-in to writable working directory
Some application will require writing files to the working directory.
In that case the setting should be changed as follows:
Docker package validation
During
docker:stage
, Docker package validation is called to check if the selected strategy is compatible with the detected Docker version.This fixes the current repeatability issue reported as #1187. If the incompatibility is detected, the user is advised to either upgrade their Docker, pick another strategy, or override the
dockerVersion
setting.Use gid=0
daemonGroup
is set toroot
instead of copying the value from thedaemonUser
setting.This matches the semantics of
USER
as well as OpenShift, which uses gid=0.