Top Related Projects
The Moby Project - a collaborative project for the container ecosystem to assemble container-based systems
A tiny but valid `init` for containers
A minimal init system for Linux containers
A minimal Ubuntu base image modified for Docker-friendliness
Quick Overview
Gosu is a lightweight tool designed to run commands as a specific user, primarily used in Docker containers. It simplifies the process of switching between root and non-root users, addressing common permission issues in containerized environments.
Pros
- Simple and lightweight, with minimal dependencies
- Improves security by allowing easy user switching in containers
- Faster and more efficient than alternatives like
su
orsudo
- Actively maintained and widely used in the Docker community
Cons
- Limited functionality compared to more comprehensive user management tools
- Primarily designed for use in Docker containers, may not be suitable for all environments
- Requires root privileges to run, which may not be ideal in some security-sensitive scenarios
- Limited documentation and examples for advanced use cases
Code Examples
- Basic usage to run a command as a specific user:
gosu username command
- Running a shell as a specific user:
gosu username sh -c 'echo "Hello, $(whoami)!"'
- Using gosu in a Dockerfile:
FROM debian:buster-slim
RUN apt-get update && apt-get install -y gosu
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
- Example entrypoint script using gosu:
#!/bin/bash
set -e
if [ "$1" = 'redis-server' ]; then
chown -R redis .
exec gosu redis "$@"
fi
exec "$@"
Getting Started
To use gosu in your Docker container:
-
Install gosu in your Dockerfile:
RUN apt-get update && apt-get install -y gosu
-
Use gosu in your entrypoint script or directly in your Dockerfile:
gosu user_name command_to_run
-
Make sure to set appropriate permissions for the gosu binary:
RUN chmod +s /usr/sbin/gosu
Remember to always use gosu with caution and follow security best practices when switching users in your containers.
Competitor Comparisons
The Moby Project - a collaborative project for the container ecosystem to assemble container-based systems
Pros of Moby
- Comprehensive container platform with a wide range of features
- Large and active community, extensive documentation
- Supports multiple architectures and operating systems
Cons of Moby
- More complex and resource-intensive
- Steeper learning curve for beginners
- Requires more setup and configuration
Code Comparison
Gosu (simple privilege dropping):
if err := gosu.Run(uid, gid, cmd, args...); err != nil {
log.Fatal(err)
}
Moby (running a container):
resp, err := cli.ContainerCreate(ctx, &container.Config{
Image: "alpine",
Cmd: []string{"echo", "hello world"},
}, nil, nil, nil, "")
if err != nil {
panic(err)
}
Summary
Gosu is a lightweight tool focused on running commands with different privileges, while Moby is a comprehensive container platform. Gosu is simpler and easier to use for specific tasks, whereas Moby offers a full suite of container management features but with increased complexity. Choose Gosu for simple privilege dropping in containers, and Moby for building, shipping, and running containerized applications at scale.
A tiny but valid `init` for containers
Pros of Tini
- Acts as a lightweight init system, handling zombie processes and signal forwarding
- Provides a more complete solution for container process management
- Supports custom entrypoints and can run as PID 1
Cons of Tini
- Slightly larger binary size compared to Gosu
- May introduce additional complexity for simple use cases
- Requires explicit installation and configuration in Dockerfiles
Code Comparison
Tini usage in Dockerfile:
FROM debian:stretch
RUN apt-get update && apt-get install -y tini
ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["your-app-command"]
Gosu usage in Dockerfile:
FROM debian:stretch
RUN apt-get update && apt-get install -y gosu
COPY entrypoint.sh /usr/local/bin/
ENTRYPOINT ["entrypoint.sh"]
Tini focuses on process management and signal handling, while Gosu primarily addresses user switching and permission issues. Tini is better suited for complex container environments requiring proper init system functionality, whereas Gosu excels in scenarios where simple user switching is the main concern. The choice between the two depends on the specific requirements of your containerized application.
A minimal init system for Linux containers
Pros of dumb-init
- Handles signal forwarding and reaping of zombie processes
- Lightweight and simple to use
- Can be used as an init system for containers
Cons of dumb-init
- Limited functionality compared to gosu
- Does not provide user-switching capabilities
- May require additional configuration for complex use cases
Code Comparison
dumb-init usage:
FROM debian:stretch-slim
RUN apt-get update && apt-get install -y dumb-init
ENTRYPOINT ["dumb-init", "--"]
CMD ["my-app", "my-app-args"]
gosu usage:
FROM debian:stretch-slim
RUN apt-get update && apt-get install -y gosu
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
CMD ["my-app", "my-app-args"]
Summary
dumb-init focuses on process management and signal handling, making it ideal for simple containerized applications. gosu, on the other hand, specializes in user-switching capabilities, which can be crucial for security and permissions management in more complex scenarios. While dumb-init is easier to implement, gosu offers more flexibility in terms of user management within containers.
A minimal Ubuntu base image modified for Docker-friendliness
Pros of baseimage-docker
- Provides a complete, init-system-enabled base image for Docker containers
- Includes useful tools and services pre-installed (e.g., SSH, cron, syslog)
- Offers better process management and zombie reaping
Cons of baseimage-docker
- Larger image size due to additional components
- More complex setup and configuration
- Potential security concerns with unnecessary services
Code Comparison
baseimage-docker:
FROM phusion/baseimage:latest
RUN /etc/my_init.d/00_regen_ssh_host_keys.sh
CMD ["/sbin/my_init"]
gosu:
FROM debian:buster-slim
RUN apt-get update && apt-get install -y gosu
COPY entrypoint.sh /usr/local/bin/
ENTRYPOINT ["entrypoint.sh"]
Key Differences
- gosu focuses on running processes with a specific user and group ID
- baseimage-docker provides a more comprehensive environment for containerized applications
- gosu is lightweight and single-purpose, while baseimage-docker offers a full-featured base image
Use Cases
- gosu: Ideal for simple containers requiring user switching
- baseimage-docker: Suitable for complex applications needing multiple services and better process management
Pros of nsenter
- Provides more advanced namespace manipulation capabilities
- Allows entering existing namespaces, not just creating new ones
- Useful for debugging and inspecting running containers
Cons of nsenter
- More complex to use and understand
- Requires root privileges or special capabilities
- Less focused on the specific use case of running commands as a different user
Code Comparison
nsenter:
int main(int argc, char *argv[])
{
int c;
while ((c = getopt_long(argc, argv, "+a:m:u:i:n:p:t:F:Z:r:w:S:G:", longopts, NULL)) != -1) {
switch (c) {
case 'a':
gosu:
func main() {
if len(os.Args) <= 2 {
usage()
}
user := os.Args[1]
Summary
nsenter is a more powerful tool for namespace manipulation, while gosu focuses specifically on running commands as a different user. nsenter offers greater flexibility but requires more expertise, whereas gosu provides a simpler solution for a common use case in containerized environments. The code snippets highlight the difference in complexity, with nsenter handling multiple options and gosu focusing on a straightforward user switch.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
gosu
This is a simple tool grown out of the simple fact that su
and sudo
have very strange and often annoying TTY and signal-forwarding behavior. They're also somewhat complex to setup and use (especially in the case of sudo
), which allows for a great deal of expressivity, but falls flat if all you need is "run this specific application as this specific user and get out of the pipeline".
The core of how gosu
works is stolen directly from how Docker/libcontainer itself starts an application inside a container (and in fact, is using the /etc/passwd
processing code directly from libcontainer's codebase).
$ gosu
Usage: ./gosu user-spec command [args]
eg: ./gosu tianon bash
./gosu nobody:root bash -c 'whoami && id'
./gosu 1000:1 id
./gosu version: 1.1 (go1.3.1 on linux/amd64; gc)
Once the user/group is processed, we switch to that user, then we exec
the specified process and gosu
itself is no longer resident or involved in the process lifecycle at all. This avoids all the issues of signal passing and TTY, and punts them to the process invoking gosu
and the process being invoked by gosu
, where they belong.
Warning
The core use case for gosu
is to step down from root
to a non-privileged user during container startup (specifically in the ENTRYPOINT
, usually).
Uses of gosu
beyond that could very well suffer from vulnerabilities such as CVE-2016-2779 (from which the Docker use case naturally shields us); see tianon/gosu#37
for some discussion around this point.
Installation
High-level steps:
- download
gosu-$(dpkg --print-architecture | awk -F- '{ print $NF }')
asgosu
- download
gosu-$(dpkg --print-architecture | awk -F- '{ print $NF }').asc
asgosu.asc
- fetch my public key (to verify your download):
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
gpg --batch --verify gosu.asc gosu
chmod +x gosu
For explicit Dockerfile
instructions, see INSTALL.md
.
Why?
$ docker run -it --rm ubuntu:trusty su -c 'exec ps aux'
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 46636 2688 ? Ss+ 02:22 0:00 su -c exec ps a
root 6 0.0 0.0 15576 2220 ? Rs 02:22 0:00 ps aux
$ docker run -it --rm ubuntu:trusty sudo ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 3.0 0.0 46020 3144 ? Ss+ 02:22 0:00 sudo ps aux
root 7 0.0 0.0 15576 2172 ? R+ 02:22 0:00 ps aux
$ docker run -it --rm -v $PWD/gosu-amd64:/usr/local/bin/gosu:ro ubuntu:trusty gosu root ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 7140 768 ? Rs+ 02:22 0:00 ps aux
Additionally, due to the fact that gosu
is using Docker's own code for processing these user:group
, it has exact 1:1 parity with Docker's own --user
flag.
If you're curious about the edge cases that gosu
handles, see Dockerfile.test-alpine
for the "test suite" (and the associated test.sh
script that wraps this up for testing arbitrary binaries).
(Note that sudo
has different goals from this project, and it is not intended to be a sudo
replacement; for example, see this Stack Overflow answer for a short explanation of why sudo
does fork
+exec
instead of just exec
.)
Alternatives
chroot
With the --userspec
flag, chroot
can provide similar benefits/behavior:
$ docker run -it --rm ubuntu:trusty chroot --userspec=nobody / ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
nobody 1 5.0 0.0 7136 756 ? Rs+ 17:04 0:00 ps aux
setpriv
Available in newer util-linux
(>= 2.32.1-0.2
, in Debian; https://manpages.debian.org/buster/util-linux/setpriv.1.en.html):
$ docker run -it --rm buildpack-deps:buster-scm setpriv --reuid=nobody --regid=nogroup --init-groups ps faux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
nobody 1 5.0 0.0 9592 1252 pts/0 RNs+ 23:21 0:00 ps faux
su-exec
In the Alpine Linux ecosystem, su-exec
is a minimal re-write of gosu
in C, making for a much smaller binary, and is available in the main
Alpine package repository. However, as of version 0.2 it has a pretty severe parser bug that hasn't been in a release for many years (and which the buggy behavior is that typos lead to running code as root unexpectedly ð¬).
Others
I'm not terribly familiar with them, but a few other alternatives I'm aware of include:
chpst
(part ofrunit
)
Top Related Projects
The Moby Project - a collaborative project for the container ecosystem to assemble container-based systems
A tiny but valid `init` for containers
A minimal init system for Linux containers
A minimal Ubuntu base image modified for Docker-friendliness
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot