Skip to content

Support custom docker daemon args #8435

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

Merged
merged 9 commits into from
Feb 28, 2022
Merged

Support custom docker daemon args #8435

merged 9 commits into from
Feb 28, 2022

Conversation

Furisto
Copy link
Member

@Furisto Furisto commented Feb 24, 2022

Description

This allows users to add arguments to the docker daemon running in the workspace. As a first step mapping the container user to the gitpod user is supported.

Related Issue(s)

Fixes #8103

How to test

  • Add environment variable DOCKER_DARGS to your user settings. The content should look like this:
    { "remap-user": "1000" } (Means container id 1000 will be mapped to gitpod user).
  • Start workspace
  • mkdir /tmp/me
  • Run docker image which supports running as unprivileged user e.g. sudo docker run -it -u node -v /tmp/me:/tmp node sh
  • Create file within container e.g. touch /tmp/foo
  • Verify that the created file has gitpod:gitpod permissions in the workspace

Hints for reviewers

  • The uidmap package needs to be installed as docker needs to create multiple user mappings which require newuidmap/newgidmap
  • The most recent version of runc needs to be installed as otherwise mounting cgroupfs will fail with when starting the container
  • Both dependencies will only be installed if the DOCKER_DAEMON_ARGS environment variable has been so that the startup performance of the first container will not be impacted for users that do no require a mapping.
  • This does not allow specifying the dockerd argument (userns-remap) directly as this would mean the user would specify ("userns-remap" : "gitpod"). We already know that the user wants to map the container user to gitpod so this is redundant. What we do not get this way is the container user that should be mapped, which means we cannot setup the /etc/subuid and /etc/subgid files for them and they would have to do it themselves.
  • Instead they can just specify the user they want to be mapped (e.g. 1000) and we ensure that this will be mapped to the gitpod user.
  • I considered modifying runc-facade instead of adding this to docker-up, but just adding the user mapping to the spec will cause file system permission errors because the rootfs needs to be chowned. This way docker will do it for us.

Release Notes

Docker in workspaces now allows mapping the user id of a container user to the workspace gitpod user

Documentation

Have not added documentation before, so any advice is appreciated.

@Furisto Furisto requested a review from a team February 24, 2022 14:16
@codecov
Copy link

codecov bot commented Feb 24, 2022

Codecov Report

Merging #8435 (e9ab07f) into main (149ca15) will increase coverage by 0.79%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #8435      +/-   ##
==========================================
+ Coverage   10.03%   10.82%   +0.79%     
==========================================
  Files          24       18       -6     
  Lines        1944     1025     -919     
==========================================
- Hits          195      111      -84     
+ Misses       1742      912     -830     
+ Partials        7        2       -5     
Flag Coverage Δ
components-gitpod-cli-app 10.82% <ø> (ø)
components-local-app-app-darwin-amd64 ?
components-local-app-app-darwin-arm64 ?
components-local-app-app-linux-amd64 ?
components-local-app-app-linux-arm64 ?
components-local-app-app-windows-386 ?
components-local-app-app-windows-amd64 ?
components-local-app-app-windows-arm64 ?
components-workspacekit-app ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
components/workspacekit/cmd/nsenter.go
components/local-app/pkg/auth/pkce.go
components/local-app/pkg/auth/auth.go
components/workspacekit/cmd/rings.go
components/workspacekit/cmd/lift.go
components/workspacekit/cmd/root.go

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 149ca15...e9ab07f. Read the comment docs.

@github-actions github-actions bot added the team: workspace Issue belongs to the Workspace team label Feb 24, 2022
@utam0k
Copy link
Contributor

utam0k commented Feb 25, 2022

First of all, thanks for the great PR.
Do you know why? I was a little curious.

The most recent version of runc needs to be installed as otherwise mounting cgroupfs will fail with when starting the container

"remap-user": "userns-remap",
}

func setUserArgs(args []string) ([]string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function seemed simpler if it was dedicated to crate args from env vars from the user that were converted to dockerd args. In other words, instead of doing both generation and addition, why not just concentrate on generation?

Suggested change
func setUserArgs(args []string) ([]string, error) {
func userArgs() ([]string, error) {
args := []string{}

And,

	uargs, err := userArgs()
	if err != nil {
		return xerrors.Errorf("cannot add user supplied docker args: %w", err)
	}
	args = append(args, uargs...)

Comment on lines 232 to 240
if id != 0 {
newfile.WriteString(fmt.Sprintf("gitpod:%d:%d\n", 1, id))
newfile.WriteString("gitpod:33333:1\n")

} else {
newfile.WriteString("gitpod:33333:1\n")
newfile.WriteString(fmt.Sprintf("gitpod:%d:%d\n", 1, 33332))
newfile.WriteString(fmt.Sprintf("gitpod:%d:%d\n", 33334, 32200))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this? I couldn't get the point what 32200 mean. What does it mean?

Suggested change
if id != 0 {
newfile.WriteString(fmt.Sprintf("gitpod:%d:%d\n", 1, id))
newfile.WriteString("gitpod:33333:1\n")
} else {
newfile.WriteString("gitpod:33333:1\n")
newfile.WriteString(fmt.Sprintf("gitpod:%d:%d\n", 1, 33332))
newfile.WriteString(fmt.Sprintf("gitpod:%d:%d\n", 33334, 32200))
}
gitpodUserId := 33333
mappingFmt := func(username string, id int, size int) string { return fmt.Sprintf("%s:%d:%d\n", username, id, size) }
if id != 0 {
newfile.WriteString(mappingFmt("gitpod", 1, id))
newfile.WriteString(mappingFmt("gitpod", gitpodUserId, 1))
} else {
newfile.WriteString(mappingFmt("gitpod", gitpodUserId, 1))
newfile.WriteString(mappingFmt("gitpod", 1, gitpodUserId-1))
newfile.WriteString(mappingFmt("gitpod", gitpodUserId+1, 33200))
}

@utam0k
Copy link
Contributor

utam0k commented Feb 25, 2022

I agree with you, we have to add the documentation. But I don't know too 😭

Have not added documentation before, so any advice is appreciated.

- Configurable runc version
- Change env name
- Converter func for user args
@Furisto
Copy link
Member Author

Furisto commented Feb 25, 2022

@utam0k PTAL

@kylos101
Copy link
Contributor

Hey @mikenikles , if we wanted to document a new capability to our docker in workspaces feature - can you help guide on what is recommended to update related documentation?

@sagor999 sagor999 linked an issue Feb 26, 2022 that may be closed by this pull request
@mikenikles
Copy link
Contributor

We don't have a page specifically for docker in workspaces, but could add one in the Configure section.

Alternatively, I'd add a note to https://www.gitpod.io/docs/environment-variables#user-specific-environment-variables given this PR introduces a new user-level environment variable.

The corresponding source file is at https://github.com/gitpod-io/website/blob/main/gitpod/docs/environment-variables.md.

@Furisto
Copy link
Member Author

Furisto commented Feb 27, 2022

First of all, thanks for the great PR. Do you know why? I was a little curious.

The most recent version of runc needs to be installed as otherwise mounting cgroupfs will fail with when starting the container

I did not try to verify which specific change in runc made the difference, although I have some suspicions.

@@ -191,25 +196,18 @@ func setUserArgs(args []string) ([]string, error) {
}

for userArg, userValue := range providedDockerArgs {
mapped, exists := allowedDockerArgs[userArg]
converter, exists := allowedDockerArgs[userArg]
Copy link
Contributor

@utam0k utam0k Feb 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love this name 👍

newfile.WriteString(fmt.Sprintf("gitpod:%d:%d\n", 33334, 32200))
newfile.WriteString(mappingFmt("gitpod", gitpodUserId, 1))
newfile.WriteString(mappingFmt("gitpod", 1, gitpodUserId-1))
newfile.WriteString(mappingFmt("gitpod", gitpodUserId+1, 32200)) // map rest of user ids in the user namespace
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good comment. Thanks.

map rest of user ids in the user namespace

Copy link
Contributor

@utam0k utam0k left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 💯

@roboquat roboquat merged commit ba168ed into main Feb 28, 2022
@roboquat roboquat deleted the fo/8103-2 branch February 28, 2022 00:30
@iQQBot
Copy link
Contributor

iQQBot commented Feb 28, 2022

too many commit 😂

@shaoye
Copy link
Contributor

shaoye commented Jun 21, 2022

1. Add environment variable DOCKER_DAEMON_ARGS to your user settings. The content should look like this:
{ "remap-user": "1000" } (Means container id 1000 will be mapped to gitpod user).
2. Start workspace
3. mkdir /tmp/me
4. Run docker image which supports running as unprivileged user e.g. sudo docker run -it -u node -v /tmp/me:/tmp node sh
5. Create file within container e.g. touch /tmp/foo
6. Verify that the created file has gitpod:gitpod permissions in the workspace

got permission denied at step 5,

touch: cannot touch '/tmp/foo': Permission denied

the node user can't create any files since /tmp is owned by gitpod user

/tmp$ ls -al
total 4
drwxr-xr-x 2 33333 33333   40 Jun 21 21:59 .
drwxr-xr-x 1 root  root  4096 Jun 21 22:00 ..

Any settings I am missing?

@utam0k
Copy link
Contributor

utam0k commented Jun 22, 2022

@shaoye Thanks for your report. Can I ask you to make sure how under /workspace/* dir is the right behavior?

@shaoye
Copy link
Contributor

shaoye commented Jun 22, 2022

@shaoye Thanks for your report. Can I ask you to make sure how under /workspace/* dir is the right behavior?

same, still got permission error if I mount /workspace/tmp/me

-v /workspace/tmp/me:/tmp

@utam0k
Copy link
Contributor

utam0k commented Jun 22, 2022

@shaoye Thanks! Can I ask you to create the issue? If you create it, we can schedule the issue.

@shaoye
Copy link
Contributor

shaoye commented Jun 22, 2022

@shaoye Thanks! Can I ask you to create the issue? If you create it, we can schedule the issue.

np! #10844

@utam0k
Copy link
Contributor

utam0k commented Jun 23, 2022

@shaoye Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-note size/L team: workspace Issue belongs to the Workspace team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[docker] Support arguments to Docker daemon
7 participants