Skip to content
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

Working directory not writable after setting dockerChmodType #1402

Closed
manuzhang opened this issue Mar 6, 2021 · 18 comments
Closed

Working directory not writable after setting dockerChmodType #1402

manuzhang opened this issue Mar 6, 2021 · 18 comments

Comments

@manuzhang
Copy link

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

  • sbt-native-packager 1.8.0
  • sbt 1.3.13
  • MacOS
  • docker
  • Docker version 20.10.2, build 2291f61
  • Debian (default image)
@muuki88
Copy link
Contributor

muuki88 commented Mar 6, 2021

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 😊

@muuki88 muuki88 closed this as completed Mar 6, 2021
@manuzhang
Copy link
Author

@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
Copy link
Contributor

muuki88 commented Mar 7, 2021

Are you looking inside or outside the container?

@manuzhang
Copy link
Author

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
Copy link
Contributor

muuki88 commented Mar 7, 2021

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

  • log file -> use an external logging service
  • configs -> either provide them at build time or mount via volume

@manuzhang
Copy link
Author

manuzhang commented Mar 8, 2021

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
Copy link
Contributor

muuki88 commented Mar 10, 2021

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 😂 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
Copy link
Author

Why does mounting a volume not work?

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

@muuki88
Copy link
Contributor

muuki88 commented Mar 11, 2021

Can you share what you have tried?

@manuzhang
Copy link
Author

manuzhang commented Mar 11, 2021

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

dockerChmodType := DockerChmodType.UserGroupWriteExecute
Docker / daemonUser := "manu"

@muuki88
Copy link
Contributor

muuki88 commented Mar 11, 2021

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

@manuzhang
Copy link
Author

docker run akka-http-petstore:0.1.0-SNAPSHOT

I'm not mounting any external volume.

@witzatom
Copy link

witzatom commented Aug 8, 2022

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
Copy link

fl-knix commented Aug 29, 2022

@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)
}

@lonnie-intercax
Copy link

lonnie-intercax commented Nov 12, 2024

sbt-native-packager 1.10.4 is concluding the Dockerfile with the following now (12-nov-2024):

COPY --from=stage0 --chown=demiourgos728:root /opt/docker /opt/docker
USER 1001:0
ENTRYPOINT ...

But the real issue is that Write permission is not set for the directories and files even for the user/owner.

@muuki88
Copy link
Contributor

muuki88 commented Nov 12, 2024

Hi @lonnie-intercax

Thanks for sharing 😊

I'm still not sure how to act on this one. There is a test covering various permission types: https://github.com/sbt/sbt-native-packager/tree/main/src/sbt-test/docker/file-permission/changes

From my experience running docker images, we faced no need for write access inside the container itself. As mentioned above

  • logging is either done to an external service or docker logs
  • generating stuff on disc is handled through mounting a volume

The various permission strategies are layed out here: https://github.com/sbt/sbt-native-packager/blob/main/src/main/scala/com/typesafe/sbt/packager/docker/DockerPermissionStrategy.scala

@lonnie-intercax
Copy link

It's easy to work around by injecting the RUN chmod -R 777 command into the Dockerfile.

It is interesting that there is not a DockerChmodType for UserGroupReadWriteExecute.

The use case is that our running app wants to create a RUNNING_PID file in its cwd.

@muuki88
Copy link
Contributor

muuki88 commented Nov 13, 2024

Hi @lonnie-intercax

That's a classic 😁 I assume you are using playframework. The PID file is a very ancient technique and not really useful in containerized environments. Here's the playframework docs on this: https://www.playframework.com/documentation/3.0.x/ProductionConfiguration#Changing-the-path-of-RUNNING_PID

Add this to your application.conf

pidfile.path = "/dev/null"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants