Moby: Tornar uid e gid configuráveis ​​para volumes compartilhados

Criado em 23 jul. 2014  ·  141Comentários  ·  Fonte: moby/moby

Forneça uma opção para tornar configurável a propriedade de volumes compartilhados.

Por exemplo, meu caso de uso atual é ter logstash-forwarder em execução em um contêiner, que tem / var / lib / docker compartilhado somente leitura como volume do host.

Como / var / lib / docker está definido como 0700 root: root no host, não consigo acessar o volume como um usuário não root.

O que eu gostaria de ter é algo como NFS, onde se pode mapear uid & gid do host para usuários e grupos no cliente.

Ou seja, docker run -v / var / lib / docker: / var / lib / docker: ro : $ user: $ group tornaria o volume disponível no contêiner como somente leitura, pertencente a $ user: $ group.

kinfeature

Comentários muito úteis

Nós realmente precisamos de uma solução go-to (não gosu) de plataforma cruzada para mapear uid / gid. Esse problema por si só causa grandes danos à maneira como o docker é percebido por novatos.

Todos 141 comentários

Não sei _como_ eles implementaram isso, e se um recurso comparável existe no Linux, mas no OS X, existe um recurso para 'ignorar a propriedade' em um volume. Efetivamente, isso fará com que _qualquer_ usuário veja os arquivos / diretórios como se fossem os proprietários.

Embora isso não sirva para todos os casos, pode ser uma boa adição

O gh # 5910 meio que lida com isso do lado do SELinux.

link: # 5910;)

A mudança do SELinux está, na verdade, mudando os rótulos do conteúdo. Potencialmente, você pode fazer a alteração no host. Não conheço outra maneira de fazer isso para UID / GID. Mas fazendo um chown -R $ UID: $ GID no ponto de montagem.

Ou você pode adicionar esse tipo de acesso usando ACLs. Mas acho que você precisará alterar todos os INODE no ponto de montagem.

Eu também preciso desse recurso.

Por exemplo, desejo criar um contêiner de web e anexar volumes com sites e configurações a ele, de modo que esse contêiner seja totalmente universal para qualquer número de sites.

No entanto, preciso obter acesso para enviar o código ao repositório do site. Como quero que meus aplicativos sejam isolados - quero que cada diretório de site seja de propriedade de um usuário / grupo separado, e seria ótimo se os arquivos gravados pelo contêiner do Docker no volume fossem de propriedade desse usuário / grupo separado.

1 para este recurso.
Não entendo como os volumes de leitura / gravação podem funcionar sem ele. Esperar que o guid / uid seja o mesmo na imagem e no host é um forte requisito incompatível com os princípios de isolamento do Docker.

Pessoalmente, estou trabalhando nisso com comandos useradd / groupadd feios e lentos para minhas ferramentas de desenvolvimento Dockerized: https://github.com/ndless-nspire/Ndless/blob/master/ndless-sdk/bin-docker/nspire-docker

Posso estar perdendo completamente o ponto. Mas eu estava lutando com um problema semelhante em que quero garantir que o usuário http tenha permissões de gravação em / var / log, que é um volume e provavelmente é do host com root: root como proprietário.

Eu resolvi isso definindo um ponto de entrada que garante que os diretórios de log sejam criados e tenham as permissões corretas. Acho que isso funciona porque o script do entrypoint é executado como root.

(comentário removido - guia errada, desculpe)

Eu hackeei isso no Ubuntu fora do Docker. Instale o pacote bindfs e vincule o diretório com o conteúdo do volume a outro caminho enquanto mapeia UID e GID para aqueles usados ​​dentro do contêiner:

sudo bindfs -u UID -g GID oldpath newpath

Em seguida, use newpath como um volume do docker. Oldpath ainda mostra a propriedade correta para o host, newpath para o convidado.

@jjv o problema é que o bindfs é MUITO MUITO lento.

@ cpuguy83 sim, está longe de ser o ideal, mas talvez ajude alguém em uma situação semelhante. Isso era para fazer as coisas funcionarem dentro de uma máquina virtual de desenvolvimento (vmhgfs não permite a configuração de UID / GID), enquanto em produção, o UID e o GID ainda precisam corresponder entre o host e o convidado ...

Na verdade, seria bom se um tipo de funcionalidade do bindfs fosse usado quando o docker implementa isso, assumindo que não cause muito impacto no desempenho. Dessa forma, você não teria que verificar se o contêiner estava sendo executado como o usuário correto. Também deve ser possível usar nomes lógicos em vez do literal uid / gid.

@jsternberg É um sucesso de desempenho TREMENDO. Muito parecido com o uso de pastas compartilhadas vbox.

+1

para os casos de uso de desenvolvimento local, acho que o Docker definitivamente precisa desse recurso. E, nesse caso, quero que esse recurso ofereça suporte ao Windows e ao OSX.

O Vagrant parece suportar isso mapeando o UID / PID do usuário do host para o usuário do vagrant. Mas para o propósito de desenvolvimento, eu realmente quero usar o Docker em vez do Vagrant, já que é muito mais leve do que o Vagrant para executar aplicativos de vários hosts.

Diga-me o que estou perdendo aqui (não tenho nenhuma experiência com Go), mas a função Go Mount () não aceita sinalizadores? Não poderíamos permitir um comando como
-v host/folder:container/folder -mount-as user:group
Você não poderia simplesmente obter o uid / gid com lookup (https://golang.org/src/os/user/lookup_unix.go)
e, em seguida, passe-os (uid = 1, gid = 1) como sinalizadores em Mount ()? (https://golang.org/src/syscall/syscall_linux.go?s=19154:19249#L754)

@krisgraham bind mounts não suporta configuração uid / gid assim.

Também separar a opção -v da opção --mount-as causa confusão quando há várias opções -v

Qual é uma boa solução alternativa para isso? Eu adoraria usar o Docker para desenvolvimento ativo, e não ter um volume montado de algum tipo não é realmente uma opção, pois eu teria que reconstruir toda vez que fizer uma alteração no meu código.

O motivo pelo qual desejo usar o Docker para desenvolvimento ativo é para que ele seja consistente com meu ambiente de produção.

@berfarah Eu uso docker para desenvolvimento ativo todos os dias.
Raramente é o caso em que preciso mexer com permanentes.
Se você estiver usando boot2docker no OSX, certifique-se de que seu diretório de trabalho esteja em / Users e você deve ficar bem.

@ cpuguy83 Obrigado pela resposta rápida. Estou tendo problemas de permissão com um ambiente Rails onde os logs não podem ser gravados e, ocasionalmente, há pontos de falha por causa das permissões. Isso se deve ao fato de meus serviços possuírem um UID diferente daquele dos arquivos.

@berfarah Minha solução alternativa é escrever meus dockerfiles de forma que os usuários / grupos de contêineres que possuem o código tenham o mesmo UID / GUID que meu usuário host. Por exemplo, como meu UID de usuário host é 1000:

RUN \
    groupadd code_executor_group && \
    useradd code_executor_user -g code_executor_group -u 1000

@berfarah Tem logs para ir stdout / stderr para RAILS_ENV = development?

@ cpuguy83 Este problema não afeta o OSX; thaJeztah comentou em 24 de julho de 2014:

no OS X, existe um recurso para 'ignorar a propriedade' de um volume. Efetivamente, isso fará com que qualquer usuário veja os arquivos / diretórios como se fossem o proprietário.

@ncjones na verdade, o mesmo se aplica ao OS X. Os "volumes" de que falei lá são os

Meu comentário foi feito para informar se algo _similar_ era possível no Linux (portanto, dentro da VM Boot2Docker)

Desculpe pela confusão aí.

@ryneeverett Obrigado, isso é útil. Você acaba modificando as permissões para 775 de 755 e 664 de 644, respectivamente, onde você precisa? editar: habilidades de leitura!

@ cpuguy83 Obrigado! Isso parece uma correção mais limitante do que a solução de @ryneeverett , pois não é algo que eu possa simplesmente levar adiante para todos os projetos.

@berfarah Que bom que você achou isso útil. Sim, apenas me certifico de que meus arquivos de host tenham as permissões corretas e que o Docker os preserve nos volumes.

+1

Isso seria extremamente útil para volumes compartilhados por meio do docker e aborda uma preocupação de segurança que tenho:

  • Volumes compartilhados em que o uid e gid do contêiner mapeiam acidentalmente para um usuário não root privilegiado no host. (por exemplo, os arquivos criados pelo contêiner no host são mapeados para um usuário que pode executar sudo sem senha, acessar conteúdo de outra forma restrito, etc.)

Corrigir isso seria muito conveniente para o pessoal da empresa executando uma tonelada de contêineres com Apache ou algum middleware e compartilhando os volumes de registro e / ou vários diretórios de conteúdo / upload. Pessoalmente, também tive algumas dores de cabeça com essas permissões durante a contêinerização de aplicativos de usuário final no Linux (como syncomm / spotify). Muitas das soluções alternativas hoje são problemáticas. Em última análise, isso deve ser corrigido dentro do docker. Eu especialmente não me sinto confortável executando scripts de shell de root como um ponto de entrada, particularmente quando este problema destaca como 0: 0 uid / gid no contêiner será mapeado para root em meu host. Eu gosto da proposta inicial "docker run -v / var / lib / docker: / var / lib / docker: ro : $ user: $ group".

@syncomm Eu faria exatamente o oposto.
O Docker não pode fazer suposições sobre a propriedade de seus dados.

A abordagem que você destaca na parte inferior do seu comentário seria factível se mapeamos automaticamente esses arquivos reais para um fs baseado em fusível, onde podemos alterar uids / gids ... e isso teria um impacto significativo no desempenho.

E logo uid 0 no contêiner não será uid 0 no host ... o que também torna a propriedade do arquivo ainda mais complicada.

Esta é uma duplicata de # 2259?

@ cpuguy83 Obrigado pelo feedback, embora eu não tenha certeza do que você quer dizer com abordagem exatamente oposta. Nuvem você explica? Eu concordaria que a propriedade dos dados não deveria ser assumida pelo docker, mas acredito que fornecer um mapeamento consistente do contêiner ao host certamente torna o trabalho de policiamento desses dados muito mais fácil para os consumidores do docker.

Eu concordo que, como a solução alternativa bindfs, torná-lo um invólucro de fusível incorreria em uma sobrecarga profunda. No entanto, deve haver uma maneira de sair desse enigma sem grandes penalidades. Essencialmente, o contêiner está se comportando corretamente (como se fosse uma máquina única separada do host), e quando montamos o diretório de um host como um volume, ele está (corretamente) vendo o sistema de arquivos POSIX lá, permissões e tudo. Infelizmente, isso torna muito difícil compartilhar dados entre os dois "hosts" de maneira consistente. Coisas como nfs, cifs, etc. são usadas para isso e suportam mapeamento uid e gid - eu acho que pode haver um paralelo aqui na resolução do problema. Honestamente, preciso me aprofundar mais no repositório para descobrir onde isso está acontecendo no código e entendê-lo melhor.

Quando as mudanças que você mencionou para a propriedade do arquivo cairão? O uid 0 NÃO sendo o mesmo para container e host me deixaria muito mais confortável criando um ponto de entrada de um script de shell raiz. Em seguida, é apenas uma questão de executar a solução alternativa sugerida de passar o uid / gid correto como um env e executar um adduser na inicialização do contêiner.

@syncomm Infelizmente, não é do meu conhecimento, não sem envolvê-los em algum outro tipo de sistema de arquivos que pode ser montado com as configurações uid / gid.

No final das contas, isso parece algo que requer suporte de kernel para remapeamento bidirecional completo de UIDs e GIDs, e nem mesmo parece fácil de gerenciar.

Para cenários não sensíveis ao desempenho, talvez algo possa ser feito usando o FUSE.

Ainda +1 para casos de uso de desenvolvimento, já que acabo com arquivos de propriedade do root em minha casa.

Para o meu caso de uso, seria suficiente se docker pudesse apenas aplicar o rótulo uid / gid e selinux personalizado ao volume do host ao criá-lo, deixando a permissão e os rótulos sozinhos se o diretório já existir. Atualmente, estou contornando isso tendo um ponto de entrada separado para a imagem que é executada como root apenas para corrigir a permissão de volume.

@ibukanov não pode aplicar uid / gid, mas o rótulo selinux está chegando.

@ cpuguy83 qual é a razão técnica para a incapacidade de aplicar um uid / gid personalizado ao criar um diretório de volume de host?

@ibukanov Veja os comentários acima.

@ cpuguy83 Simplesmente não vejo nos comentários qual é o problema. Para o meu caso de usuário, não preciso de nenhum remapeamento de uid / gid. Atualmente dentro do contêiner, ao executar como root, posso chown uid:gid /host_volume && chmod 770 /host_volume . O que seria bom se o docker pudesse fazer isso sozinho ao criar o diretório no host atrás de / host_volume. Dessa forma, eu não precisaria de um hack para fornecer um ponto de entrada extra no contêiner apenas para realizar a operação acima como uma raiz do contêiner e sempre posso executar o código usando uma conta não-root.

@ibukanov Ah, isso é uma coisa diferente.
O Docker não faz, propositalmente, alterações nos diretórios do host.
Se fizermos o # 9092, se o docker tiver criado o dir, ele o tratará como um volume normal (ou seja, copia tudo no caminho do volume no contêiner para o host e chmod / chown como estava no contêiner).

@ cpuguy83 - bem, o docker muda algo no host quando cria o volume do host ausente. Mas # 9092 soa como se realmente resolveria meu caso de uso.

@ cpuguy83 escreveu:

E logo uid 0 no contêiner não será uid 0 no host ... o que também torna a propriedade do arquivo ainda mais complicada.

Existe um problema para rastrear isso? Não consegui encontrar um.

Obrigado!

Existe um problema para rastrear isso? Não consegui encontrar um.

@dato Procure por "Namespace do usuário"; uma implementação inicial pode ser encontrada aqui: https://github.com/docker/docker/pull/12648 e aqui https://github.com/docker/docker/pull/11253

Mas existem várias discussões / problemas anteriores a isso :)

+1

só para saber que estou no mesmo barco que todos:

Estou usando a imagem nginx e montando um volume em / usr / shared / nginx / html para desenvolvimento local. Nginx é executado como www-data , mas o volume é montado como 1000:staff e eu obtenho 403 forbidden .

@MrMMorris Não acho que seja o mesmo barco - esse problema ocorre quando os arquivos criados dentro de um contêiner (em um volume montado) não podem ser lidos fora do contêiner sem acesso ao sudo. Seu usuário www-data precisa apenas de acesso de leitura aos arquivos montados, então você deve ser capaz de apenas chmod a+r em seus arquivos.

@ncjones chmod / chown parece não ter efeito sobre as permissões no contêiner

Estou tão confuso porque juro que funcionou em vários pontos durante o meu uso ...

Tudo bem, isso é constrangedor ...

Parece que depois de atualizar para compor 1.3.0rc-1 (provavelmente não) OU excluir todos os meus contêineres / imagens e executar docker-compose up novamente corrigiu tudo .... Não há mais 403 forbidden

Eu sabia que estava funcionando antes de alguma forma, então peguei a velha abordagem de rm -rf * .

Eu também preciso que esse problema seja resolvido de alguma forma. Eu tenho uma imagem docker que uso para executar alguns trabalhos pesados ​​de compilação que devem ser isolados. Então o container deve subir, receber alguma entrada externa, processar e então produzir os binários (saída). Sem o gerenciamento de permissões adequado, é um pesadelo tentar fazer isso funcionar. Minhas imagens devem ser portáteis, então não posso presumir muito sobre o host.

@alercunha No seu caso, parece

@alercunha
Resolvemos esse problema em uma configuração de compilação, fazendo com que o contêiner do Docker execute o chown da saída da compilação. Nosso Dockerfile conterá algo como:

env USER_ID 1000
env GROUP_ID 1000
cmd bash -lc '\
  build.sh && \
  chown -R $USER_ID:$GROUP_ID build \
'

O uid / gid real do usuário do host Docker pode então ser fornecido ao contêiner quando executado. Por exemplo, um comando de construção do Jenkins usará algo como:

docker run \
  -e USER_ID=`id -u` \
  -e GROUP_ID=`id -g` \
  -v $basedir:/workspace

@motin Construir como root é algo que estou tentando evitar, pois estou usando docker / buildroot para construir vários projetos de terceiros. A ideia é ter alguma proteção contra que o código-fonte atrapalhe meu ambiente de construção. Portanto, construir como root não parece uma boa ideia.

@ncjones Obrigado! Essa é realmente uma boa ideia, pode funcionar bem como uma solução no meu caso particular.

@alercunha Nesse caso, pode valer a pena considerar o uso de imagens / containers separados para cada projeto de terceiros. Isso também poderia beneficiar melhor a comunidade de código aberto, por exemplo, se você enviar imagens docker oficiais para a construção de cada um desses projetos de terceiros.

Para conceder todos os privilégios a www-data, você pode usar:

RUN usermod -u 1000 www-data

Foi encontrado um problema ao executar um trabalho no docker em um volume montado. Os arquivos resultantes pertenciam ao root e não podiam ser gerenciados pelo usuário que executava o comando docker. A solução alternativa atual é executar após o trabalho para corrigir as permissões.

docker run -t --rm \
    -v $PWD:/usr/src/app \
    -w /usr/src/app \
    debian:wheezy chown -R $(id -u):$(id -g) ./

é possível fazer com que o docker altere a permissão de volumes montados baseados em host para pertencer ao usuário especificado no comando USER do DockerFile? É claro que as permissões devem ser configuráveis, mas podemos fazer com que isso tenha o comportamento padrão.

@ mig-foxbat
Para meus propósitos, seria suficiente se o docker apenas definir a propriedade e a permissão no diretório do host a partir do ponto de montagem na imagem quando o diretório do host for criado pela primeira vez. Se o diretório do host já existir, o docker pode deixá-lo sozinho.

@ mig-foxbat & @ibukanov o pré-requisito obrigatório para mim, ao abrir este problema, era que as permissões no sistema de arquivos hosts não fossem alteradas (como em ter algum mapeamento virtual no contêiner semelhante ao que se pode fazer com _NFS_).

O que você está tentando fazer pode ser feito facilmente hoje, executando _chown_ em algum script de inicialização dentro do seu contêiner.

Adoro a arquitetura de plug-in de volume que está por vir, mas prefiro que a equipe do Docker adicione esse recurso. O Docker funciona bem até que você use volumes com usuário não root em seu contêiner. Então, quando as coisas (por exemplo, o registro) não funcionam, você joga seu laptop pela janela do Starbucks ou encontra o item stackoverflow mencionado acima.

+1 Eu gostaria que os contêineres executassem aplicativos como usuário não root, o que se torna complicado devido a esse problema.

Por que não implementar esse recurso usando o recurso id_map do LXC?

Acabei de notar que a resposta para "id_map" (também conhecida como suporte a namespace de usuário) já foi mencionada acima por @thaJeztah

Embora seja necessário um pouco de trabalho extra para definir as permissões, estamos executando dezenas de contêineres como não-root e evitando os problemas de permissão. A maioria de nossos contêineres de dados começa com algo como:
ENV CONTAINER_USER cônsul
ENV CONTAINER_UID 312312
EXECUTE adduser -D $ CONTAINER_USER -u $ CONTAINER_UID
EXECUTE mkdir -p / var / consul /
CMD chown $ CONTAINER_USER. $ CONTAINER_USER / var / consul /

Com o contêiner de execução real sendo semelhante em termos de configuração das informações de UID / useradd. Este é um trabalho duplicado (ter que definir o UID no contêiner de dados e no contêiner de execução), no entanto, é bastante menor. Ter o docker para alterar as permissões ou mapear as permissões em tempo real adicionaria alguma complexidade decente e os usuários teriam que ser mais cuidadosos do ponto de vista da segurança. Eu também sou a favor de tudo o que ajude a reduzir a complexidade da linha de comando, então, se tudo estiver contido no dockerfile, será um pouco mais direto o que está acontecendo.

Agora, há a observação acima de tentar acessar arquivos de host em um contêiner com algum tipo de mapeamento. Acho que essa é certamente uma proposição arriscada. Muitas vezes, tentar compartilhar arquivos sem mapeamento de host direto é provavelmente a melhor solução, caso contrário, você estará invertendo um pouco a segurança do docker. Em vez de um contêiner com menos permissões do que teria de outra forma, você está falando sobre um contêiner rodando como não-root e com acesso de nível raiz (caso de uso freqüentemente presumido) para hospedar arquivos. Permissões de grupo ou outras soluções que considero que devem prevalecer na maioria das situações.

Eu contornei isso com um script de shell do ponto de entrada que executa o chown no diretório montado e executa o subcomando via su.

Um exemplo em um contêiner solr em que o diretório / data é montado como um volume do host:

#!/bin/bash

chown -R $SOLR_USER:$SOLR_USER /data

su -c "$@" -m $SOLR_USER

_USER POLL_

_A melhor maneira de ser notificado quando há mudanças nesta discussão é clicando no botão Inscrever-se no canto superior direito._

As pessoas listadas abaixo apreciaram sua discussão significativa com um +1 aleatório:

@jcercurati
@iangelov
@scue
@razvanphp
@fantasma
@andrerocker
@anandnalya
@ddopson
@tem sobre
@hadim
@iyn
@cgrantcharovtp
@sandytrinh
@gomex
@DrBenton
@tehmaspc
@segphault
@avaz
@edavism
@ayeo
@stanislavb
@smebberson
@ tony-kerz
@msierks
@pdonorio
@ samsong8610
@ qm78
@joshughes
@roelvanduijnhoven
@vladimirbright
@ ava-dylang

Dizendo qualquer coisa nesses tópicos, um usuário se inscreve automaticamente, então sim, todas essas pessoas estão inscritas, a menos que tenham cancelado a inscrição intencionalmente. (também não tenho certeza _quem_ você está se referindo como your )

Isso é definitivamente obrigatório. O Docker deve remapear UIDs corretamente. Caso contrário, tudo criado a partir do contêiner para o volume do sistema operacional host é propriedade do root. A solução alternativa é terrível - mudar os usuários dentro do contêiner, o que leva a todos os tipos de complicações, tendo que chown em todos os lugares, o Dockerfile fica feio. E o pior de tudo os UIDs de codificação tornam os contêineres impossíveis de transportar!

+1 Este recurso seria muito apreciado, pois desejo evitar alternar entre o contêiner docker e meu sistema host, apenas para evitar sobrescrever a id dos usuários nos arquivos.

Obter a personalização do UID é possível agora, mas dentro das seguintes restrições:

  • A personalização do Uid é possível fazendo com que o contêiner aceite os uid (s) de que precisa por meio da variável de ambiente. Isso dá ao host controle total sobre os uid (s) que o contêiner usa e tem um benefício adicional: várias variáveis ​​podem ser definidas com o mesmo valor de uid. O remapeamento de Uid é incapaz de suportar o mapeamento de múltiplos uids de contêiner para um único uid de host, uma vez que o mapeamento deve ser 1: 1. Por exemplo, se o mapeamento desejado era de fato que o aplicativo deveria ser executado como uid = 0, você poderia fazer isso injetando variáveis, mas não via remapeamento de uid. Veja @ncjones e @mitchcapper solução acima.
  • A raiz uid = 0 notavelmente, no entanto, não pode ser alterada para um valor diferente, exceto por remapeamento: # 12648.

Quase todas as estruturas de desenvolvimento web modernas têm uma pasta de logs e uma pasta de cache que está dentro do projeto, definida na configuração do projeto e compartilhada por meio do volume montado. Usei o vboxfs primeiro, mas era muito lento. Achei docker-machine-nfs para criar montagens NFS e é rápido, mas agora meus arquivos da web em contêineres são propriedade de 502: dialout e não podem ser chmod ou chown, então meu aplicativo da web não será executado. Eu tentei o docker vagrant box, mas ele requer o vagrant com todos os diferentes env vars e configs, e ainda não funciona com docker-machine. Mesmo que seja um processo manual de curto prazo, há uma solução alternativa para adicionar o usuário 502 aos dados www ou algo assim? É tudo de que preciso para estar no negócio!

+1

Para aqueles que seguem este; há atualmente um PR para um recurso experimental que mudará recursivamente a propriedade de arquivos montados em bind. Deve ser usado com cuidado, porque esse recurso mudará os arquivos no host (que pode não ser o que você deseja em todos os casos); consulte https://github.com/docker/docker/pull/14632 (e https://github.com/docker/docker/pull/16767)

+1

A propósito, resolvi esse problema ao usar ACL

@kvaps ,

@posita , aposto que @kvaps está falando sobre POSIX ACLs . Se eu estiver certo, isso não é o mesmo que a solicitação de OP.

@posita , @denydias , desculpe pela longa resposta. Sim, estou falando sobre isso.
Tenho muitos containers como owncloud, samba e minidlna. Todo mundo trabalha com diferentes uid e gid.
Todos eles operam com os mesmos arquivos. O que todos podem ler e gravar arquivos, montei o sistema de arquivos com a opção acl na máquina host e dei a todos direitos de uid e gid para esses arquivos simplesmente, como o comando chown :

# give access for owncloud (apache uid 33):
setfacl -R -m "u:33:rwx" /data
# give access for samba (uid 1000):
setfacl -R -m "u:1000:rwx" /data
# give access for minidlna (uid 997):
setfacl -R -m "u:997:r-x" /data
# preserve this permissions for new files and folders:
setfacl -R -d -m "u:33:rwx" /data
setfacl -R -d -m "u:1000:rwx" /data
setfacl -R -d -m "u:997:r-x" /data

@kvaps , o comando setfacl não funciona em Dockerfile . Exemplo:

FROM nginx

ADD data/conf /etc/nginx

RUN mkdir -p /etc/nginx/sites-enabled

VOLUME /etc/nginx

RUN setfacl -dR -m u:1000:rwx /etc/nginx && setfacl -R -m u:1000:rwx /etc/nginx

Resultado:

root<strong i="12">@3975ac4fba98</strong>:/etc/nginx# getfacl sites-enabled/
# file: sites-enabled/
# owner: root
# group: root
user::rwx
group::r-x
other::r-x

As ACLs funcionam apenas depois de montadas na máquina host e executam setfacl . Versão do Docker:

Client version: 1.7.1
Client API version: 1.19
Go version (client): go1.4.2
Git commit (client): 786b29d
OS/Arch (client): linux/amd64
Server version: 1.7.1
Server API version: 1.19
Go version (server): go1.4.2
Git commit (server): 786b29d
OS/Arch (server): linux/amd64

Isso é muito simples de fazer direito e também muito simples de estragar. Portanto, não estrague tudo!
A maneira certa de fazer isso é: Na primeira vez que o contêiner é executado, o host injeta quais uids o contêiner deve usar (conforme já descrito acima).
A pior maneira de fazer isso é: esperar que o contêiner imponha seus requisitos de uid ao host. Isso está errado, errado, errado. Por exemplo, considere dois contêineres que compartilham uma montagem comum: um contêiner grava arquivos para servir e outro contêiner executa httpd para servir os arquivos. Agora, se esses dois contêineres tiverem definições concorrentes para uid, este sistema estará quebrado na pior das hipóteses ou deficiente na melhor das hipóteses. As ACLs que estão sendo definidas não farão nenhum sentido para o host e provavelmente serão mais amplas do que o necessário, o que significa que agora é um problema de segurança. Por favor não faça isso!! Faça isso da forma correta.

Concordou. Deixar o mapeamento entre o UID e o contêiner é uma solução boa o suficiente. Só queria que o docker liderasse pelo exemplo e suportasse esses mapeamentos UID / GID nas imagens oficiais do docker.

Resolvido em tempo de execução , sem a necessidade de chown .

Usei algo próximo à solução @ncjones , mas não quero chown arquivos porque não quero que sejam modificados no host. Portanto, optei por alterar o UID na inicialização do contêiner.

Eu crio um usuário dedicado em meu Dockerfile :

RUN adduser --no-create-home --disabled-login --gecos "" username --uid 1000

Eu defino um script de inicialização em meu Dockerfile :

CMD ["/run.sh"]

Eu tenho esta linha em meu script /run.sh :

usermod -u $USER_ID username

Agora posso escolher USER_ID quando o contêiner começa:

docker run -e USER_ID=$(id -u)

Conseguido resolver isso usando os novos argumentos do dockerfile. Não é necessário fazer nada de especial após a construção do contêiner, então pensei em compartilhar. (Requer Docker 1.9)

No Dockerfile:

# Setup User to match Host User, and give superuser permissions
ARG USER_ID=0
RUN useradd code_executor -u ${USER_ID} -g sudo
RUN echo 'code_executor ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER ${USER_ID} 

Então, para construir:

docker build --build-arg USER_ID=$(id -u)

Todo o resto está normal :)

Editar:
Eu escrevi este post sobre o problema errado (era outro relacionado ao boot2docker).
Desculpa.

@ pa-de-solminihac usermod -u $USER_ID username mudará o ID de usuário de username e acionará uma mudança de propriedade dos arquivos em username 's HOME, mas todos os arquivos anteriormente pertencentes a username fora de sua casa provavelmente se tornará ilegível / não gravável, pois agora pertencem a um usuário diferente

@riquito eu uso com um usuário dedicado, criado no Dockerfile :

adduser --no-create-home --disabled-login --gecos "" username --uid 1000

Portanto, não há arquivos pertencentes a username . Então eu acho que não há problema;)

Para sua informação, setfacl _não_ funciona em volumes que remontam ao OS X:

root<strong i="7">@0da3c867240d</strong>:~# setfacl --default --recursive --modify u:500:rwx --modify g:500:rwx /opt/test
setfacl: /opt/test: Operation not supported

(Neste caso, /opt/test é hospedado no OS X por meio da máquina Docker e Boot2Docker. Consulte também boot2docker / boot2docker # 581.)

@posita Você está usando o virtualbox para hospedar sua imagem boottodocker? Em caso afirmativo, isso pode realmente ser uma limitação da maneira como o virtualbox faz as pastas compartilhadas. Eu tive muitos problemas para fazer qualquer tipo de permeabilidade regular através da pasta compartilhada da caixa virtual.

@ava-dylang, esse é um bom ponto. A descrição acima é feita por meio da Docker Machine com o driver Parallels , que usa a implementação de pastas compartilhadas nativas do Parallels, que parece igualmente limitada. (Consulte também https://github.com/docker/machine/issues/13#issuecomment-164320881 em relação a uma proposta para esses tipos de ambientes.)

FWIW, eu estava tendo problemas com a propriedade do arquivo em meu utilitário, Scuba .

Eu contornei o problema adicionando um script "init" que cria um usuário no contêiner com o mesmo UID / GID do usuário de chamada no host. Veja JonathonReinhart / scuba # 11 e JonathonReinhart / scuba # 13.

Agora os arquivos criados no contêiner parecem exatamente como foram criados no host.

_Atualização: _ Isso causou problemas (JonathonReinhart / scuba # 22). Em vez disso, corrigi-lo gerando meus próprios /etc/passwd e amigos, com base no uid / gid do usuário host, e injetei-o no contêiner (consulte JonathonReinhart / scuba # 24).

+1

Para torná-lo mais sustentável e seguro quando o host é executado no modo multilocatário.

Tive problemas de permissão com essas instalações do Wordpress, quando você compartilha todo o Wordpress do host para o contêiner com um volume.

Em minha pilha, tenho uma imagem base, que é um debian com minhas modificações básicas e todas as outras imagens serão construídas a partir dessa imagem.

Na imagem de base, tenho esta parte:

### Start of Nginx WEBSERVER setup
RUN mkdir -p /var/www
# Modify www-data user and set UID, GID to 500
# https://muffinresearch.co.uk/linux-changing-uids-and-gids-for-user/
RUN groupmod -g 500 www-data \
    && usermod -u 500 www-data \
    #&& `find / -user 33 -exec chown -h 500 {} \;` \
    #&& `find / -group 33 -exec chgrp -h 500 {} \;` \
    && usermod -g 500 www-data \
    && chown -R www-data:www-data /var/www \
    && chmod g+s /var/www
### End of Nginx WEBSERVER setup

www-data não é criado por instalações php ou nginx. É um usuário / grupo padrão definido no Debian e talvez em outras distros. Algumas instalações de PHP e Nginx sugerem o uso desse usuário em seus arquivos de configuração.

Se o UID / GID do usuário host for 500 (a maioria dos UID / GID do usuário não root padrão do linux é 500 ou 1000), este script altere o UID / GID do usuário www-data para 500 de 33. Desta forma, se você compartilha qualquer coisa do host, o Docker pensa que esses arquivos e pastas pertencem ao usuário www-data !

Nos arquivos de configuração do PHP-FPM, defina o usuário e o grupo como www-data também.

Em seu Dockerfile nginx, você também deve definir isto:

# Allow Nginx to access /var/run/php-fpm/php-fpm.sock
RUN usermod -aG www-data nginx

Desta forma, nginx user pode acessar os arquivos pertencentes a www-data (você pode definir o nome de usuário do nginx nos arquivos de configuração do nginx).

Depois desse hack, minha instalação do Wordpress não teve NENHUM problema de permissão! Todos os arquivos residem no host + a atualização do Wordpress funciona perfeitamente!

@DJviolin Não tenho certeza se um problema como esse é o lugar adequado para um tutorial do Wordpress, e hesito em expor aqui. No entanto, para os infelizes novatos que podem de alguma forma tropeçar nisso:

  1. O que você postou faz muitas suposições sobre a instalação - ou seja, valores UID / GID, nomes de usuário e grupo, etc. Não é terrivelmente portátil entre as distribuições.
  2. Mais importante, fornecer acesso gravável para todos (0777) a toda a instalação do Wordpress é extremamente perigoso e explicitamente não recomendado na documentação oficial do WP. Além disso, com tudo isso montado no host, você acabou de permitir uploads arbitrários da Internet para gravar no sistema de arquivos _host_.

@jantman Desculpe, meu mal. Parece que o primeiro hack também resolve os problemas de permissão. Não há necessidade de alterar nenhuma permissão padrão.

Obviamente, todos precisam descobrir o UID: GID de seu usuário host e alterar a configuração de acordo com isso. Além disso, conecte-se com um usuário novo ou já existente na missão. O meu é um exemplo de trabalho para uma pilha viva.

Até que docker não dê uma solução para este problema, as premissas permanecerão.

Minha solução é a mesma que @JonathonReinhart ou @ pa-de-solminihac.

Você pode fazer isso criando volumes locais, ele acabou de pousar no mestre https://github.com/docker/docker/pull/20262.

Fechando isso como corrigido.

Olá, eu também tive que fazer uma solução alternativa no meu dockerfile:

...
COPY start.sh /root/start.sh
CMD /root/start.sh

e então em start.sh

usermod -u $USER_ID www-data
exec php-fpm

Como $ USER_ID pode ser injetado como parâmetro de ambiente, é possível usar essa imagem do docker sem modificação.

De qualquer forma, acho que deveria haver mais funcionalidade embutida para esse tipo de coisa e estou me perguntando como usar esses volumes locais sugeridos por @calavera , alguém pode dar um exemplo?

@ keywan-ghadami Eu também estava intrigado com os volumes locais. O problema é que você precisa primeiro criar o sistema de arquivos (ou usar tmpfs). Portanto, ele não usa / var / lib / docker. Na verdade, você não pode usar um subdiretório de _qualquer_ FS existente porque as montagens de ligação não suportam a opção uid . Não sei para que servem os volumes locais; você também pode criar e montar o FS você mesmo e, em seguida, usar um volume de host normal ( -v my-created-fs:container-mount-point ).

Estou muito atrasado para este tópico, mas o problema foi resolvido? Não está 100% claro de todos os diferentes problemas mencionados aqui. @brthor parece ter a melhor solução pelo que posso ver, mas envolve opções de linha de comando que poderiam ser adicionadas mais facilmente ao Dockerfile e feitas nos bastidores.

Para mim, codificar UID e GID é uma má ideia para portabilidade entre ambientes e não vejo a necessidade de adicionar argumentos de linha de comando toda vez que inicializo um contêiner ou construo uma imagem quando poderia ser uma opção simples no Dockerfile. Não poderia haver uma opção simples no Dockerfile ou talvez por meio de docker-compose.yml onde você pode especificar algum tipo de opção "map uid from host"?

Pode haver uma boa solução por aí, mas eu realmente não consigo descobrir isso na documentação ou neste tópico.

Obrigado @alvinchevolleaux , posso confirmar que estamos usando a solução que postei acima no CI para https://github.com/dotnet/cli com sucesso há meses.

Recomendo!

@brthor Sim, é o que eu export USER_ID=$(id -u) ao meu .bash_profile, então é tudo automático para meus vários ambientes. Muito Obrigado.

Conforme discutido acima, ao compartilhar conteúdo de sua pasta de início em um contêiner, adicione uma conta de usuário com o mesmo UID da sua. Aqui está um truque para lidar se o seu UID não for 1000. Presumo que cada usuário construa sua própria imagem do docker a partir do Dockerfile.

Seu Dockerfile deve conter:

RUN useradd --uid 1000 -m vagrant
USER vagrant

A constante 1000 é substituída por seu UID real usando um filtro _git_. Execute o seguinte em seu host:

git config filter.uidfix.smudge "sed s/1000/$UID/g"
git config filter.uidfix.clean "sed s/$UID/1000/g"

Finalmente, adicione um arquivo .gitattributes para aplicar o filtro git:

Dockerfile filter=uidfix

Isso funciona substituindo 1000 pelo seu UID real ao fazer o checkout do Dockerfile _smudging_ do arquivo. O Git irá _ limpar_ o arquivo (colocando de volta 1000 ) quando você fizer o commit. Todos os comandos executados no contêiner são executados como vagrant usuário com o UID correto.

Costura este tíquete deve ser reaberto, pois todas as soluções fornecidas aqui são apenas soluções alternativas
Encontrei uma solução bem documentada e mais completa em https://github.com/rocker-org/rocker/blob/master/rstudio/userconf.sh
Ele usa argumentos de tempo de execução que possibilitam o uso de imagens pré-compiladas, o que não é possível com o filtro git

@calavera Não entendo sua solução.

por exemplo

$ mkdir /tmp/test
$ sudo docker volume create --name=test -d local --opt type=nfs --opt device=/tmp/test:/data --opt o=notime,nosuid,uid=11459,git=11459
$ sudo docker run -t -i -v test:/tmp fedora bash -i
[.. $] touch /tmp/foo.txt
[.. $] exit
$ ls -la /tmp/test

Quando eu olho no diretório / tmp / test, não há arquivos. Não parece que a pasta / tmp / test esteja sendo montada no contêiner ... Em vez disso, está criando um volume do contêiner. O que realmente não é o que eu quero.

Não consigo encontrar nenhuma documentação que me diga quais são as opções --opt válidas. Portanto, estou realmente imaginando como isso deve funcionar.

Reabra este problema. O novo driver local não parece abordar de forma alguma o problema de montagem de diretórios de host locais com IDs de usuário selecionados.

@calavera
Você pode comentar sobre como podemos resolver o problema de arquivos sendo removidos como root com volumes de host locais? Tenho visto esse problema surgir com frequência, especialmente ao usar o docker para cenários de CI.

Olhando para o PR vinculado, não vejo nada imediatamente óbvio, mas tenho certeza de que estou perdendo algo 😄

Tenho usado variações dessa solução alternativa em meus contêineres, como docbill / docker-force. Porém, me ocorre que uma solução mais limpa é um container que só se encarrega de fazer a squashroot ...

Usar algo como bindfs para local deve ajudar. Você pode executá-lo com -o map = $ (id -u) / root: @ $ (id -g) / @root (assumindo que não há espaço de nome de usuário) e você deve ver os arquivos como seus fora do contêiner, embora sejam de propriedade de enraíze-se dentro dele.

@ktosiek Obrigado, parece que tem potencial. Você poderia postar um exemplo completo de docker run comando ou sessão de console?

Alguém poderia postar uma atualização de status sobre este problema: foi fechado como "não corrige" ou foi realmente implementado? O tópico é bastante longo, então, por favor, me perdoe, pois não consigo ver de relance qual é a resolução.

@quinncomendant, consulte https://github.com/docker/docker/issues/7198#issuecomment -191990887
Informe se não funcionar.

Obrigado @ LK4D4.

Para resumir, o problema foi fechado com uma correção que permite opções de montagem para o driver de volume local .

Pelo que eu posso dizer, não há opções para definir o usuário: grupo de um _host-diretório montado como um volume_ (corrija-me se essa opção existir - é o que vim aprender aqui).

@quinncomendant correto; ao montar um diretório de host por ligação, você deseja que o contêiner use os arquivos que estão lá como estão, o que inclui permissões. Se você deseja alterar essas permissões, você precisa fazer isso no host, antes de montá-las

@quinncomendant Ou, em termos mais simples, NÃO
solução fornecida não faz nada para resolver o problema
relatado, nem há planos para resolver esse problema.

Em 6 de julho de 2016 às 17:20, Sebastiaan van Stijn [email protected]
escreveu:

@quinncomendant https://github.com/quinncomendant correto; quando
montagem de um diretório host que você deseja que o contêiner use os arquivos que
estão lá como estão, o que inclui permissões. Se você quiser alterá-los
permissões, você precisa fazer isso no host, antes de montá-los

-
Você está recebendo isso porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/docker/docker/issues/7198#issuecomment -230909967 ou mudo
o segmento
https://github.com/notifications/unsubscribe/ADBcWLihVjI1FoSMLKu7DyhwFOpGX0KKks5qTBwMgaJpZM4CQMjR
.

Este parece ser um problema que NÃO SE ENCONTRA. Sempre parece que os aspectos de _desenvolvimento_ da conteinerização continuam a ser negligenciados e ainda exigem que escrevamos hacks.

Eu me deparei especificamente com esse problema porque os desenvolvedores que estou apoiando estão executando comandos de geração de arquivos de projeto de dentro de um contêiner e de fora para o volume montado no host (instalar essas ferramentas no host anula completamente o propósito de usar um contêiner, certo?).

Eles querem iterar rapidamente nesses arquivos, mas como outros neste tópico indicaram, eles são gravados como o uid / gid com o qual o contêiner está sendo executado, o que exige que eles sejam executados corretamente no host para serem posteriormente manipulados (por um IDE, por exemplo).

Realmente precisa haver uma maneira _docker specific_ de shim em um uid / gid temporário nesses tipos de casos.

@boj Este é o cenário exato que encontrei durante o desenvolvimento do Scuba . Minha solução atual cria, durante a inicialização, um usuário no contêiner com o mesmo uid / gid do usuário host. Não é a solução mais simples, mas funciona bem.

@JonathonReinhart Obrigado, você me deu um pouco de inspiração.

Acabei escrevendo um wrapper de script chamado do host assim (eles usam django neste caso):

# bin/manage.py
#!/bin/sh

docker run -v $(pwd):/usr/local/prj -it --entrypoint="/usr/bin/python3.4" -w /usr/local/prj -u $(id -u):$(id -g) prj src/prj/manage.py $@

@boj O problema potencial com essa solução ( -u $(id -u):$(id -g) ) é que não há nenhuma entrada em /etc/passwd ou /etc/group para esse uid / gid no contêiner: https: // github .com / JonathonReinhart / scuba / issues / 11

@JonathonReinhart Noted. Neste caso específico, só me preocupo com os arquivos gravados no host do desenvolvedor e se eles têm as mesmas permissões do usuário do host.

Não se preocupe com o que realmente acontece em tempo de execução, isso era tudo de que eu realmente precisava.

@JonathonReinhart

Se o software no contêiner precisar de uma entrada em / etc / passwd ou / etc / group, torne-as graváveis ​​para todos na imagem e adicione as entradas necessárias na inicialização.

Portanto, a solução mencionada por @JonathonReinhart (mapeamento uid / gid) resolve isso.

Parece que isso já é compatível com runc (https://github.com/opencontainers/runc/blob/8c9db3a7a5145f6b26c8051af319eee6f72c9ca8/libcontainer/configs/config.go#L19-24). No Docker, há a configuração userns-remap para o deamon, aqui basicamente precisaríamos ter mais granularidade (nível de contêiner em vez de nível de deamon), há algum interesse / plano para oferecer suporte a isso?

Este docker-compose.yml não funciona:

version: '2'

services:
  app:
    build: ./app
    container_name: myapp
    volumes:
      #- "../app:/root/www/myapp:rw"
      - myapp:/root/www/myapp:rw

volumes:
  myapp:
    driver: local
    driver_opts:
      o: uid=500
      device: ../app

Alguém pode me dizer por quê? Estou seguindo as diretrizes oficiais: https://docs.docker.com/engine/reference/commandline/volume_create/#/driver -specific-options

É possível anexar volumes nomeados do host? Com driver_opts você pode definir uid (e talvez gid ?).

+1

+1

@lazyuser @xiaods Pare com os +

@bamarni Sim, acho que o novo recurso de namespace de usuário pode resolver isso, mas como você disse, ele precisaria ser implementado por contêiner. O resultado final seria: Um contêiner está sendo executado como o que ele pensa ser "root", mas na verdade é o UID / GID passado na linha de comando docker run . Os arquivos "sairiam" do contêiner pertencente ao usuário apropriado.

@lazyuser @xiaods @JonathonReinhart você deve clicar no botão +1 abaixo da descrição do problema

Ou apenas clique em inscrever-se à direita se quiser apenas notificações ...

@JonathonReinhart : definitivamente, passei pelo documento novamente, mas infelizmente ter o mapeamento de todo o daemon em vez de por contêiner foi uma decisão consciente devido a uma limitação:

Nota: A restrição de mapeamento único por daemon está em vigor agora porque o Docker compartilha camadas de imagem de seu cache local em todos os contêineres em execução na instância do mecanismo. Como a propriedade do arquivo deve ser a mesma para todos os contêineres que compartilham o mesmo conteúdo de camada, a decisão foi mapear a propriedade do arquivo no docker pull para o usuário do daemon e mapeamentos de grupo para que não haja atraso para a execução dos contêineres após o download do conteúdo. Esse design preserva o mesmo desempenho para docker pull, docker push e inicialização do contêiner que os usuários esperam com os namespaces de usuário desabilitados.

_ (https://docs.docker.com/engine/reference/commandline/dockerd/#/daemon-user-namespace-options) _

Caro @JonathonReinhart , @ pa-de-solminihac e @nalipaz ,
Obrigado pelo seu esforço em educar a mim e a outros para não deixar comentários não relacionados ao problema, fazendo exatamente isso! Para sua informação, o Github não permite a pesquisa de questões em que uma pessoa está inscrita sem pelo menos comentar sobre elas. Para obter mais informações, consulte https://github.com/isaacs/github/issues/283. Ironicamente, o problema do Github é quase da mesma idade que o de Docker, e ambos parecem ter prioridades semelhantes.

A todos, desculpe pelo spam. Na primeira vez, foi uma solução alternativa para o bug do github mencionado anteriormente e, desta vez, não resisti e contei a ironia da situação.

Resolvi isso usando

RUN export DEBIAN_FRONTEND=noninteractive \
  && apt -y update \
  && apt -y install inotify-tools \
  && inotifywait -m -r /mount -e create --format '%w%f' \
    | while read f; do chown $(stat -c '%u' /mount):$(stat -c '%g' /mount) $f; done

Isso funciona instruindo inotifywait a observar quaisquer novos arquivos ou diretórios criados no diretório / mount. Quando percebe um, ele muda a propriedade para o mesmo usuário e grupo da pasta / mount. Usei a representação inteira de ambos, caso o usuário / grupo host não exista no container. Dentro do contêiner, não importa quem o possui, porque tudo funciona como root. Fora do contêiner, o sistema de arquivos do host mostra a mesma propriedade de qualquer diretório montado em / mount.

Eu o projetei deliberadamente para definir apenas a propriedade de arquivos e diretórios recém-criados, a fim de preservar a propriedade de arquivos e diretórios pré-existentes. É mais seguro do que explodir tudo isso com uma instrução chown -R toda vez que o sistema de arquivos é montado. Se as permissões uniformes funcionam para o seu projeto e você deseja uma solução mais simples que seja executada com mais eficiência, consulte o inotify-hookable .

Aviso: Uma vez que um inotify watch será estabelecido por subdiretório, é possível que a quantidade máxima de inotify watch por usuário seja atingida. O máximo padrão é 8192; ele pode ser aumentado gravando em / proc / sys / fs / inotify / max_user_watches.

@ codekitchen-ws Outro aviso: um arquivo pode ser movido após a criação e antes da alteração do proprietário. Dependendo do shell, você também desejará citar "$f" (para evitar a divisão de palavras no caminho).

+1

@briansrepo Essa é uma abordagem interessante. Se estiver em uma instrução Dockerfile RUN , que é executada no momento da compilação. Como ele poderia saber o usuário docker run em tempo de execução?

@btiernay Obrigado! Ele não usa o UID do usuário que disparou a imagem. Ele copia especificamente o usuário host e o grupo host de qualquer diretório host montado em / mount. Ele não examina nenhum outro arquivo ou subdiretório. Cabe ao usuário certificar-se de que as permissões estão definidas para algo que ele possa escrever no sistema host.

Exemplo: Suponha que o diretório do host / var / www / html seja propriedade de brian: www-data. Você inicia uma imagem que monta o diretório do sistema host / var / www / html no diretório da imagem / mount. Em seguida, você cria /mount/index.html de dentro da imagem. Se você verificar a propriedade de /var/www/html/index.html no sistema host, ele será propriedade de brian: www-data.

Com base nesse exemplo, digamos que você tenha um diretório de host / var / www / html / upload de propriedade de www-data: www-data. Lembre-se de que o diretório do host montado / var / www / html ainda pertence a brian: www-data. Agora vá para a imagem e crie /mount/upload/file.pdf. Se você verificar o arquivo host /var/www/html/upload/file.pdf, ele será propriedade de brian: www-data , não www- data: www-data , porque o diretório host montado / var / www / html é propriedade de brian: www-data. Faz sentido?

TL; DR: Você passa o usuário: grupo que deseja usar, transferindo o diretório do host montado para usuário: grupo.

@briansrepo obrigado pela explicação. Tudo isso faz sentido, mas ainda não entendi como isso pode funcionar dentro de um RUN . Eu acho que isso precisa ser executado em segundo plano quando o contêiner é executado (ou seja, docker run ).

@btiernay Eu também gosto dessa ideia.
@briansrepo pelo menos cobre o que acontece nos contêineres.
O processo de construção ainda pode ser tratado com algo como

RUN usermod -u 1000 www-data

No entanto, essas ainda são soluções alternativas.

Em minha pilha LEMP, tenho esta pré-configuração do Nginx em meu Dockerfile base:

### Start of Nginx WEBSERVER setup
RUN mkdir -p /var/www
# Modify www-data user and set UID, GID to 500
# https://muffinresearch.co.uk/linux-changing-uids-and-gids-for-user/
RUN groupmod -g 500 www-data \
    && usermod -u 500 www-data \
    && usermod -g 500 www-data \
    && chown -R www-data:www-data /var/www \
    && chmod g+s /var/www
### End of Nginx WEBSERVER setup

Este é um hack onde todos os arquivos recém-criados de uma sessão ssh do host obtendo o uid, gid de 500 e nginx não terão acesso a esses arquivos eventualmente (porque o usuário ou grupo com o id 500 não existia no contêiner). Você pode verificar qual número de uid e gid deve criar para o usuário www-data ao copiar novos arquivos para o volume compartilhado no host de uma sessão SSH e, posteriormente, docker exec neste contêiner e olhando os arquivos do uid, gid.

O problema que encontrei, se copiei novos arquivos para a pasta compartilhada na máquina host (que você acessou por uma sessão ssh, como em uma instância do CoreOS no DigitalOcean), o Nginx não teria acesso aos arquivos recém-criados. Portanto, se você quiser compatibilidade absoluta com privilégios, terá que compartilhar seus arquivos do servidor da web no contêiner do Docker na criação dos contêineres (pelo menos esse era o caso há 1 ano, quando me deparei com esses problemas de uid e gid com volumes compartilhados) .

OU você também pode instalar o serviço ssh no contêiner docker que compartilha os arquivos com o contêiner nginx, desta forma, se você copiar / modificar os arquivos, eles terão o uid correto, gid. Mas contra as práticas recomendadas do Docker, você deve usar docker inspect vez de sessões ssh, porque "Docker não é uma VM" (seria uma solução muito fácil, certo?).

Na minha opinião, um contêiner do Docker deve atuar como um serviço ou um executável e não deve tomar como refém meus arquivos do servidor da web se eu não quiser. Banco de dados é um tipo de coisa diferente (às vezes), mas não vejo por que não seria possível obter a mesma infraestrutura de contêiner do Santo Graal, onde todos os seus arquivos de banco de dados estáticos, servidores da Web e de banco de dados vivendo fora dos contêineres (mas os contêineres podem modifique-os (como excluir, criar, modificar) e você também pode modificá-los sem quaisquer problemas de privilégio do host.

Com docker volume create --opt você pode definir uid, gid, mas não é verdadeiro para docker-compose : https://github.com/docker/compose/issues/3715

Nós realmente precisamos de uma solução go-to (não gosu) de plataforma cruzada para mapear uid / gid. Esse problema por si só causa grandes danos à maneira como o docker é percebido por novatos.

Criamos uma solução alternativa para esse problema que altera as permissões de usuário / grupo e arquivo de um contêiner do Docker que foram definidas no tempo de construção para o UID / GID com o qual o contêiner foi iniciado no tempo de execução.

O projeto e as instruções de instalação estão em: https://github.com/boxboat/fixuid

Exemplo: o contêiner do Docker foi criado usando o usuário / grupo dockeruser:dockergroup como UID / GID 1000:1000 . O host está executando como UID / GID 1001:1002 . A imagem foi executada com docker run -u 1001:1002 . fixuid irá:

  • altere dockeruser UID para 1001
  • altere dockergroup GID para 1002
  • altere todas as permissões de arquivo do antigo dockeruser:dockergroup para 1001: 1002
  • atualize $ HOME dentro do contêiner para dockeruser $ HOME
  • agora o contêiner e o host UID / GID coincidem e os arquivos criados no contêiner em montagens de host coincidem

Ele pode ser executado como ENTRYPOINT ou como parte de um script de inicialização. Ele é instalado no contêiner como um binário de propriedade de root com o bit setuid e aumenta os privilégios para fazer as alterações apropriadas. Ele só deve ser usado em contêineres de desenvolvimento.

Se isso for útil, o Docker Engine pode ser capaz de incorporar parte ou toda a lógica por meio de sinalizadores em docker run

Resolvido usando docker volume .

@hashar como? você pode dar um exemplo, por favor

então ainda não há solução para isso a não ser usar gosu e um script de entrypoint ?!

Por enquanto, parece que há 2 opções de solução alternativa para isso, até que a equipe do Docker faça uma atualização oficial sobre isso.

É uma pena que isso ainda seja um problema. Em teoria, há remapeamento de usuários, mas não é amigável.

Esta página foi útil?
0 / 5 - 0 avaliações