Skip to content

Support docker run with --user $(id -u):$(id -g) cli arg (shared process error) #439

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

Closed
satlus opened this issue Apr 5, 2019 · 18 comments
Closed
Labels
enhancement Some improvement that isn't a feature

Comments

@satlus
Copy link

satlus commented Apr 5, 2019

Test environment

Host OS: OSX 10.14.4
Docker: 2.0.0.3 (31259)
image: codercom/code-server:1.621

Request

Hi,

We run docker in a locked down environment where we alias the docker run cli command to prepend --user $(id -u):$(id -g) on all host operating systems. This is a security constraint we can't remove. When i try to execute code server simulating this environment it throws a shared process error. Any ideas on an approach to resolve?

Repro

docker run -it -p 127.0.0.1:8443:8443 -v "${PWD}/codeserver:/home/coder/project" -u $(id -u):$(id -g) -v "${PWD}/codeserver/.cache:/.cache" -v "${PWD}/codeserver/.local:/.local" codercom/code-server:1.621 --allow-http --no-auth
INFO  code-server development
INFO  Additional documentation: http://github.com/codercom/code-server
INFO  Initializing {"data-dir":"/.local/share/code-server","extensions-dir":"/.local/share/code-server/extensions","working-dir":"/home/coder/project","log-dir":"/.cache/code-server/logs/20190405152816797"}
INFO  Starting webserver... {"host":"0.0.0.0","port":8443}
WARN  No certificate specified. This could be insecure.
WARN  Documentation on securing your setup: https://github.com/codercom/code-server/blob/master/doc/security/ssl.md
WARN  Launched without authentication.
INFO   
INFO  Started (click the link below to open):
INFO  http://localhost:8443/
INFO   
INFO  Starting shared process [1/5]...
INFO  Starting shared process [2/5]... {"error":"Exited with 1"}
INFO  Starting shared process [3/5]... {"error":"Exited with 1"}
/src/packages/server/out/cli.js:325
return"boolean"==typeof e.extractComments?(r.preserve=i,r.extract=/^\**!|@preserve|@license|@cc_on/i):"string"==typeof e.extractComments||e.extractComments instanceof RegExp?(r.preserve=i,r.extract=e.extractComments):"function"==typeof e.extractComments?(r.preserve=i,r.extract=e.extractComments):Object.prototype.hasOwnProperty.call(e.extractComments,"condition")?(r.preserve=i,r.extract=e.extractComments.condition):(r.preserve=!1,r.extract=i),["preserve","extract"].forEach(e=>{let t,n;switch(typeof r[e]){case"boolean":r[e]=r[e]?()=>!0:()=>!1;break;case"function":break;case"string":if("all"===r[e]){r[e]=(()=>!0);break}if("some"===r[e]){r[e]=((e,t)=>"comment2"===t.type&&/^\**!|@preserve|@license|@cc_on/i.test(t.value));break}t=r[e],r[e]=((e,n)=>new RegExp(t).test(n.value));break;default:n=r[e],r[e]=((e,t)=>n.test(t.value))}}),(e,t)=>{if(r.extract(e,t)){const e="comment2"===t.type?`/*${t.value}*/`:`//${t.value}`;n.includes(e)||n.push(e)}return r.preserve(e,t)}})(e,c,u));const

Error: ENOENT: no such file or directory, uv_os_get_passwd
    at new t.Server (/src/packages/server/out/cli.js:325:105264)
    at e.exports.w.on (/src/packages/server/out/cli.js:325:102138)
    at emitTwo (events.js:131:20)
    at e.exports.emit (events.js:214:7)
    at handleUpgrade.t (/src/packages/server/out/cli.js:489:29992)
    at e.exports.completeUpgrade (/src/packages/server/out/cli.js:489:32439)
    at e.exports.handleUpgrade (/src/packages/server/out/cli.js:489:31556)
    at upgrade (/src/packages/server/out/cli.js:489:29963)
    at emitThree (events.js:136:13)
    at u.emit (events.js:217:7)
    at onParserExecuteCommon (_http_server.js:542:14)
    at socketOnData (_http_server.js:477:3)
    at emitOne (events.js:116:13)
    at Socket.emit (events.js:211:7)
    at Socket.Readable.read (_stream_readable.js:475:10)
    at flow (_stream_readable.js:846:34)
    at emitReadable_ (_stream_readable.js:514:3)
    at emitReadable (_stream_readable.js:507:7)
    at addChunk (_stream_readable.js:274:7)
    at readableAddChunk (_stream_readable.js:250:11)
    at Socket.Readable.push (_stream_readable.js:208:10)
    at TCP.onread (net.js:601:20)
@satlus satlus added the enhancement Some improvement that isn't a feature label Apr 5, 2019
@satlus
Copy link
Author

satlus commented Apr 10, 2019

after educating myself a bit on docker user and group management, this does not appear to be something that is fixable by codercom devs. I will be closing this issue. Here's a brief synopsis:

  • coder (properly) adds a user to the image and ensures codeserver is executed as that user
  • this user will resolve to 1000:1000 in /etc/passwd in the container per ubuntu defaults
  • if you are lucky enough to be running on a host where your user id equals 1000, passing -u $(id -u) will just work; otherwise, which I assume is most cases, it will not

in short docker is doing what it's supposed to, and my uid does not resolve to the uid that codeserver is instructed to run as. We are discussing other approaches as passing the -u $(id -u) flag does not seem like something that will scale appropriately, particularly for third party images.

@satlus satlus closed this as completed Apr 10, 2019
@ericcollazo
Copy link

after educating myself a bit on docker user and group management, this does not appear to be something that is fixable by codercom devs. I will be closing this issue. Here's a brief synopsis:

  • coder (properly) adds a user to the image and ensures codeserver is executed as that user
  • this user will resolve to 1000:1000 in /etc/passwd in the container per ubuntu defaults
  • if you are lucky enough to be running on a host where your user id equals 1000, passing -u $(id -u) will just work; otherwise, which I assume is most cases, it will not

in short docker is doing what it's supposed to, and my uid does not resolve to the uid that codeserver is instructed to run as. We are discussing other approaches as passing the -u $(id -u) flag does not seem like something that will scale appropriately, particularly for third party images.

If you are building your own Docker image you can designate what user you want the container to use in your Dockerfile.

@satlus
Copy link
Author

satlus commented Apr 11, 2019

Unless I'm mistaken you would need to have a custom docker build for every user in the organization that wants to use code server with this approac. This could be in the thousands in our world, and is not scalable. The core requirement is dynamic uid/guid resolution to be mapped at runtime, not build time. Ideally a single hosted instance could support multiple users, obviating the need for this, which seems like it's being investigated:
#33

Until then we are looking at podman.io, or possibly creating our own image that includes a PAM module that could resolve our UIDs from a directory server. Or even potentially an approach like fixid: https://boxboat.com/2017/07/25/fixuid-change-docker-container-uid-gid/. Very early days for us.

@sr229
Copy link
Contributor

sr229 commented Apr 12, 2019

Hey @satlus I did the usermode changelist for it and this seems to be similar to the OpenShift case as stated in #223. Kindly reopen as I would be happy to investigate and properly fix it

@satlus satlus reopened this Apr 12, 2019
@satlus
Copy link
Author

satlus commented Apr 13, 2019

Cool, re-opened. I think I see the approach here per your openshift fork. I noticed that you're doing an append to the container /etc/passwd file based on uid:guid in the entry point script. I've done similar in my fork, but using a sudo groupmod so we don't keep appending duplicate entries:
master...satlus:satlus-nonrootuser

I'm currently at a very low bandwidth area and can't build the docker image to test - when I can I'll post back.

@kylecarbs
Copy link
Member

Any update on this @satlus ?

@satlus
Copy link
Author

satlus commented Apr 26, 2019

I was able fiddle with this today, and I couldn't get an approach using sudo usermod or vanilla usermod, to work. I captured the UID:GID in container env vars, and then ran usermod in the entrypoint script prior to execution. the problem is that if you do this with the host user, you're not in /etc/passwd and usermod fails (sudo will fail as well for the same reason). More details here:
70424c8

disclaimer: I shouldn't be considered authoritative on this subject I'm experimenting. I'll play around a bit more, but including trying sr229's approach

@ibnesayeed
Copy link

If I supply -u (or --user) flag to keep file permissions correct as if I were to play with my files on the host, the service is failing to create a ./cache directory. Is it something that can be configured to create under the /tmp instead of the root of the file system?

$ mkdir /tmp/foo
$ cd /tmp/foo
$ docker run --rm -it \
  -u $(id -u):$(id -g) \
  -p 127.0.0.1:8443:8443 \
  -v $PWD:/home/coder/project \
  codercom/code-server --allow-http --no-auth
(node:6) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
ERROR { [Error: EACCES: permission denied, mkdir '/.cache']
  [stack]: 'Error: EACCES: permission denied, mkdir \'/.cache\'',
  [message]: 'EACCES: permission denied, mkdir \'/.cache\'',
  errno: -13,
  code: 'EACCES',
  syscall: 'mkdir',
  path: '/.cache' }

@satlus
Copy link
Author

satlus commented May 2, 2019

If you scroll horizontally in the example I posted that invokes the docker run command you'll see I pass volume mounts to make the directories writable. You'll need to do the same. I have examples in my fork:
https://github.com/satlus/code-server/blob/satlus-nonrootuser/DockerLaunchCommands.MD

I think you will still hit the shared process issue I originally reported, which is ultimately due to this:
#439 (comment)

@ibnesayeed
Copy link

I guess https://github.com/boxboat/fixuid can help resolve the UID/GID issue at least.

@MostHated
Copy link

I guess https://github.com/boxboat/fixuid ([![](chrome-extension://bcnkgcoohaaaclieohdlkphgfinkgbfm/link-icon.png) 9 hours ago](https://github.com/boxboat/fixuid/tree/0ec93d22e52bde5b7326e84cb62fd26a3d20cead)) can help resolve the UID/GID issue at least.

This looks great. I was just now coming across this same issue with mounted partitions. I am about to try that out right now. It seems extremely useful in many situations. Thanks for the link. : D

@satlus
Copy link
Author

satlus commented May 3, 2019

added fixuid in my branch, and it's working in my test environment. I've submitted a PR for review here:
#640

@kylecarbs let me know what you think

@ibnesayeed
Copy link

You beat me to this PR @satlus, good job! 👍

I have provided some feedback in the PR, but I am no authority on this repo.

@sr229
Copy link
Contributor

sr229 commented Jun 21, 2019

CC @satlus I'll be including your modifications in my Docker image so people can pre-test it and have their feedback.

@sr229
Copy link
Contributor

sr229 commented Jun 21, 2019

The thing is I'll be re-modifying it to use a production image of the editor will update when I have a working image.

@satlus
Copy link
Author

satlus commented Jul 12, 2019

@sr229 I've been pulled away from this for a couple of weeks, but this image was running successfully in our environment. Happy to discuss mods via #640. Ideally it would eventually get merged, as I see it as non invasive.

@vsnine
Copy link

vsnine commented Aug 1, 2019

Wanted to add my band-aid for this problem by overriding the entrypoint with the following script.

#!/bin/bash
sudo /usr/sbin/groupadd <my gid>
sudo /usr/sbin/usermod -u <my uid> -g <my gid> coder
/usr/bin/dumb-init /usr/local/bin/code-server --disable-telemetry

@nhooyr
Copy link
Contributor

nhooyr commented Jan 28, 2020

Will deal with this soon. See #1307

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Some improvement that isn't a feature
Projects
None yet
Development

No branches or pull requests

9 participants