sbt / sbt-native-packager

sbt Native Packager
https://sbt-native-packager.readthedocs.io/en/stable/
BSD 2-Clause "Simplified" License
1.59k stars 439 forks source link

Working directory not writable after setting `dockerChmodType` #1402

Closed manuzhang closed 3 years ago

manuzhang commented 3 years ago

Expected behaviour

The working directory is writable by the running process after setting as per File Permission:

import com.typesafe.sbt.packager.docker.DockerChmodType

dockerChmodType := DockerChmodType.UserGroupWriteExecute

Actual behaviour

The working directory is not writable since its owner is root rather than user

$ ls -l /opt
total 4
drwxr-xr-x 1 root root 4096 Mar  6 01:55 docker

Information

muuki88 commented 3 years ago

Thanks @manuzhang for this issue 😃

This sounds more like a configuration issue on your end. You need to change the user if you want the directory inside the containers to be owned by some other user

Docker / daemonUser := "your-user"

See https://sbt-native-packager.readthedocs.io/en/latest/formats/docker.html#environment-settings for more details for environmental settings 😊

manuzhang commented 3 years ago

@muuki88

Even if I add

Docker / daemonUser := "manu"

The directory /opt/docker is not writable by "manu"

$ ls -l /opt
total 4
drwxr-xr-x 1 root root 4096 Mar  7 04:16 docker
muuki88 commented 3 years ago

Are you looking inside or outside the container?

manuzhang commented 3 years ago

Inside the container and I want to create a file under /opt/docker. This is the staging Dockerfile.

FROM openjdk:8 as stage0
LABEL snp-multi-stage="intermediate"
LABEL snp-multi-stage-id="59495a5c-a50d-40c3-a389-b4cb72bf1d44"
WORKDIR /opt/docker
COPY 1/opt /1/opt
COPY 2/opt /2/opt
USER root
RUN ["chmod", "-R", "u=rwX,g=rwX", "/1/opt/docker"]
RUN ["chmod", "-R", "u=rwX,g=rwX", "/2/opt/docker"]
RUN ["chmod", "u+x,g+x", "/1/opt/docker/bin/akka-http-petstore"]

FROM openjdk:8 as mainstage
USER root
RUN id -u manu 1>/dev/null 2>&1 || (( getent group 0 1>/dev/null 2>&1 || ( type groupadd 1>/dev/null 2>&1 && groupadd -g 0 root || addgroup -g 0 -S root )) && ( type useradd 1>/dev/null 2>&1 && useradd --system --create-home --uid 1001 --gid 0 manu || adduser -S -u 1001 -G root manu ))
WORKDIR /opt/docker
COPY --from=stage0 --chown=manu:root /1/opt/docker /opt/docker
COPY --from=stage0 --chown=manu:root /2/opt/docker /opt/docker
USER 1001:0
ENTRYPOINT ["/opt/docker/bin/akka-http-petstore"]
CMD []
muuki88 commented 3 years ago

Thanks for the Dockerfile.

It looks like there's still root being used.

Whenever this issue comes up I tend to ask what you are trying to achieve? Usually it's one of the following

manuzhang commented 3 years ago

My server needs to generate a swagger.json file at runtime depending on staging / production environment to serve requests through swagger UI.

Besides, it looks weird to have a working directory owned by root rather than the current user.

muuki88 commented 3 years ago

My server needs to generate a swagger.json file at runtime depending on staging / production environment to serve requests through swagger UI.

Why does mounting a volume not work?

Besides, it looks weird to have a working directory owned by root rather than the current user.

I find docker most of the time weird :joy: However we apply this principle to all formats. Least amount of privileges as possible. The start scripts are executable and the rest is readable. Especially in container environments write access is most of the time unnecessary.

manuzhang commented 3 years ago

Why does mounting a volume not work?

That should work. I tried to follow the doc but it appears not accurate.

muuki88 commented 3 years ago

Can you share what you have tried?

manuzhang commented 3 years ago

https://github.com/manuzhang/akka-http-petstore/blob/docker/build.sbt#L32

dockerChmodType := DockerChmodType.UserGroupWriteExecute
Docker / daemonUser := "manu"
muuki88 commented 3 years ago

But how do you start your container. How do you actually mount an external volume?

manuzhang commented 3 years ago
docker run akka-http-petstore:0.1.0-SNAPSHOT

I'm not mounting any external volume.

witzatom commented 2 years ago

Hey, this issue is closed but I still find the behavior weird and inconsistent. Running into the same issue.

Inside the container, in the working directory I cannot:

$ touch test
touch: test: Permission denied

yet i can

$ touch bin/test

where bin is a folder that is in my working directory.

I get your point of restricting the permissions, but its called a working directory for a reason. Its not a solution to mount a volume on the files that the application might want to create, as that is an unknown set, sometimes even an infinite set (for example logs). Its possible to work around this, but I doubt that this is intended behavior.

Workaround, something like (change your working directory):

  .settings(dockerCommands := dockerCommands.value.flatMap {
    case Cmd("USER", "1001:0") =>
      Seq(
        Cmd("RUN", "chown -R 1001:0 /opt/api"),
        Cmd("USER", "1001:0")
      )
fl-knix commented 2 years ago

@witzatom Thanks for this, and agreed; servers may need write access to the working directory for a variety of reasons. In my case, we log to both a file and an external service so that we can monitor logs with zero latency via files when needed. Here's the complete workaround for anyone else who needs this:

// Give the run user access to the working directory before switching away from ROOT
// https://github.com/sbt/sbt-native-packager/issues/1402
dockerCommands := dockerCommands.value.flatMap {
  case Cmd("USER", "1001:0") =>
    Seq(
      Cmd("RUN", "chown -R 1001:0 /opt/docker"),
      Cmd("USER", "1001:0"),
    )
  case cmd => Seq(cmd)
}