Esta é uma ferramenta simples cultivada pelo simples fato de que su
e sudo
têm um comportamento muito estranho e muitas vezes irritante de tty e defensor do sinal. Eles também são um pouco complexos de configurar e usar (especialmente no caso do sudo
), o que permite uma grande expressividade, mas cai plano se tudo o que você precisa é "executar esse aplicativo específico como esse usuário específico e sair do oleoduto ".
O núcleo de como gosu
funciona é roubado diretamente de como o próprio Docker/LibContainer inicia um aplicativo dentro de um contêiner (e, de fato, está usando o código de processamento /etc/passwd
diretamente da base de código da libcontainer).
$ 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)
Depois que o usuário/grupo é processado, mudamos para esse usuário, exec
o processo especificado e o próprio gosu
não é mais residente ou envolvido no ciclo de vida do processo. Isso evita todas as questões de passagem de sinais e tty, e os punga com o processo que invocava gosu
e o processo sendo invocado por gosu
, onde eles pertencem.
O caso de uso principal do gosu
é deixar de root
para um usuário não privilegiado durante a inicialização do contêiner (especificamente no ENTRYPOINT
, geralmente).
Os usos de gosu
além disso podem muito bem sofrer de vulnerabilidades como CVE-2016-2779 (da qual o caso de uso do Docker nos protege naturalmente); Veja tianon/gosu#37
para alguma discussão sobre esse ponto.
Etapas de alto nível:
gosu-$(dpkg --print-architecture | awk -F- '{ print $NF }')
como gosu
gosu-$(dpkg --print-architecture | awk -F- '{ print $NF }').asc
como gosu.asc
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
gpg --batch --verify gosu.asc gosu
chmod +x gosu
Para obter instruções explícitas Dockerfile
, consulte INSTALL.md
.
$ 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
Além disso, devido ao fato de gosu
estar usando o próprio código do Docker para processar estes user:group
, ele tem uma paridade exato de 1: 1 com o próprio --user
do Docker.
Se você está curioso sobre os casos de borda que gosu
lida, consulte Dockerfile.test-alpine
para o "Suite de teste" (e o script test.sh
associado que o envolve para testar binários arbitrários).
(Observe que sudo
tem objetivos diferentes deste projeto e não se destina a ser uma substituição sudo
; por exemplo, consulte essa resposta de pilha para uma breve explicação de por que sudo
faz fork
+ exec
para apenas exec
.)
chroot
Com o sinalizador --userspec
, chroot
pode fornecer benefícios/comportamentos semelhantes:
$ 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
Disponível em util-linux
mais recente ( >= 2.32.1-0.2
, em 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
No ecossistema alpino Linux, su-exec
é uma reescrita mínima de gosu
em C, criando um binário muito menor e está disponível no main
repositório de pacotes alpinos. No entanto, na versão 0.2, ele possui um bug bastante grave que não está em um lançamento há muitos anos (e qual o comportamento de buggy é que os erros de digitação levam à execução do código como root inesperadamente?).
Não estou muito familiarizado com eles, mas algumas outras alternativas que eu sou conhecimento incluem:
chpst
(parte do runit
)