Compose: Usando o comando shell em docker-compose.yml

Criado em 27 out. 2016  ·  41Comentários  ·  Fonte: docker/compose

Olá, existe uma maneira de usar comandos shell no arquivo docker-compose.yml ?
Aqui está meu caso de uso:

 version: '2'
 services:
   ci:
     image: jenkins
     volumes:
       - ./data:/var/jenkins_home
       - /var/run/docker.sock:/var/run/docker.sock
       - $(command -v docker):/usr/bin/docker
     groupadd:
       - $(stat -c %g /var/run/docker.sock)
     ports:
       - "8080:8080"
       - "50000:50000"

Atualmente, está me apresentando este erro:

ERROR: Invalid interpolation format for "volumes" option in service "ci": "${command -v docker}:/usr/bin/docker"
kinquestion

Comentários muito úteis

Seria muito útil ter ...

Todos 41 comentários

Olá @zkanda ,

Desculpe, isso não é algo que apoiamos. Normalmente, isso é feito definindo variáveis ​​de ambiente e usando a substituição de variável dentro do arquivo Compose.

@ shin- obrigado, posso contornar as variáveis ​​de ambiente. Além disso, .env parece muito útil também.
Documentos relevantes: https://docs.docker.com/compose/environment-variables/#/the -env-file

@zkanda , você conseguiu fazer isso funcionar? Tentei no meu arquivo .env

DOCKER_BIN=`which docker`

e em docker-compose.yml

jenkinsmaster:
  build: jenkins-master
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - ${DOCKER_BIN}:/usr/bin/docker
  ports:
    - "50000:50000"

Mas eu continuo recebendo

Cannot create container for service jenkinsmaster: create `which docker`: "`which docker`" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed.

Portanto, parece que os comandos são interpretados como strings no arquivo .env ?

Os comandos não são expandidos pelo Compose, em .env ou em outro lugar.

Seria muito útil ter ...

+1

Aqui está um caso de uso. Ao configurar o Kafka, ele precisa do IP da máquina host. Tenho o seguinte script para fazer isso para mim:

DOCKER_HOST_IP=$(ifconfig | grep 'inet .*br' | sed -E 's/.*inet (.*) netmask.*/\1/')

Eu faço referência a esse IP no env. Não posso mais executar docker-compose up porque preciso executá-lo de antemão. E eu preciso informar os outros desenvolvedores da equipe sobre isso.

+1

Seria útil obter o usuário atual, como em:

services:
  foo:
    image: bar:latest
    user: ${CURRENT_USER-$(id -u):$(id -g)}

Deve haver outros casos de uso também ...

A propósito, não entendi que ${BAZ-default} funcione no Compose se não pudermos executar o restante das funcionalidades do Bash ... (pelo que eu sei, o - é uma das funcionalidades de manipulação de variáveis ​​do Bash, como substituição por ${VAR/search/replace} , por exemplo)

Sim @ davi5e ... O que eu estava tentando:

version: "3.7"

services:
  orchestrator:
    build: .
    ports:
      - "2000:2000"
    # Use type host until we can test link
    network_mode: "host"
    environment:
      - NODE_ENV=development
      - LOCAL_USER_ID=${id -u}

@ davi5e outro caso de uso é quando você deseja criar um volume docker e vinculá-lo ao diretório do repositório git. Este banho absoluto será cauteloso para cada desenvolvedor da equipe.

+1
Por favor, reabra o problema

+1
meu caso de uso é publicar um intervalo de portas que é determinado em função de uma porta "base"

Isso seria muito útil para definir variáveis ​​UID / GID, pois isso é praticamente um requisito para usar o Docker em um ambiente de desenvolvimento (sem a necessidade de usar scripts para definir isso em um arquivo .env).

+1

Pode usar isso para rotular / marcar as imagens geradas pelo docker compose com a tag git e o hash de confirmação:

Em .env :

GIT_VERSION=$(git describe --always --dirty --abbrev)
OUTER_PORT=6970

Em docer-complse.yml :

version: '3'
services:
  nginx:
    restart: always
    build:
        context: ./nginx
        labels:
          org.label-schema.schema-version: "1.0"
          org.label-schema.version: "${GIT_VERSION}"
          org.lavel.schema.url: "https://mydocu-server.company.com/vcs/${GIT_VERSION}"
    ports:
      - ${OUTER_PORT}:8080

Para aqueles que estão fazendo isso em desenvolvimento, se o seu shell definir a variável UID , você pode passá-la ao construir a imagem de desenvolvimento local. Como a imagem do desenvolvimento local não é compartilhada, você não precisa se preocupar com conflitos de uid com seus colegas de trabalho.

+1

@con-f-use Fazer isso enviará apenas o comando real e não o resultado dos meus testes, o único hack que tive sucesso até agora foi escrever um script wraper docker compose que configura a variável de ambiente.

+1

TL; DR se você quiser exportar essas variáveis ​​do arquivo .env :

# set the path of .env file here
ENV_FILE="${ENV_FILE:-local.env}"
while IFS= read -r line; do
  export "$line"
done < <( grep --color=never -E -v -e '^#' -e '^[[:space:]]*$' "${ENV_FILE}" )

Como usar:

  • Digite-o na linha de comando e pressione Enter para modificar seu ambiente de shell atual

OU

  • Salve-o como script bash e fonte-o

Ressalvas:

  • Salvar isso como um script e executá-lo não exportará magicamente essas variáveis ​​em seu ambiente de shell atual. Você terá que adquirir ou fazer algo sofisticado eval .
  • (Talvez seja uma coisa boa?) Ele substituirá as variáveis ​​existentes com o mesmo nome em $ENV_FILE

Explicação: aqui

Dê uma olhada no direnv para automatizar tudo isso https://direnv.net/

Na sexta-feira, 28 de junho de 2019, 12h57, Sudarshan Wadkar [email protected]
escrevi:

TL; DR se você deseja exportar essas variáveis ​​do arquivo .env:

defina o caminho do arquivo .env aqui

ENV_FILE = "$ {ENV_ FILE: -local.env }" enquanto IFS = ler -r linha; Faz
exportar "$ line" feito <<(grep --color = never -E -v -e '^ #' -e '^ [[: space:]] * $' "$ {ENV_FILE}")

Como usar:

  • Digite na sua linha de comando
  • Salve-o como script bash e fonte-o

Ressalvas:

  • Salvar isso como um script e executá-lo não vai exportar magicamente aqueles
    variáveis ​​em seu ambiente shell atual. Você terá que terceirizar ou fazer
    alguma avaliação extravagante.
  • (Talvez seja uma coisa boa?) Ele substituirá as variáveis ​​existentes com as mesmas
    nome em $ ENV_FILE

Explicação: aqui
https://explainshell.com/explain?cmd=while+IFS%3D+read+-r+line%3B+do+export+%22%24line%22%3B+done+%3C+%3C%28grep+--color%3Dno+ -v + -e +% 27% 5E% 23% 27 + -e +% 27% 5E% 5B% 5B% 3Aspace% 3A% 5D% 5D *% 24% 27 +% 24% 7BENV_FILE% 7D% 29

-
Você está recebendo isto porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/docker/compose/issues/4081?email_source=notifications&email_token=AACHRDBQXQZTC5FXTOFL6UTP4XOBJA5CNFSM4CUISSSKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODYZUTRQ#issuecomment-506677702 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AACHRDGJ6FAQBEDLBSRVS6TP4XOBJANCNFSM4CUISSSA
.

Sim, direnv é bom, mas não tenho certeza se será útil com o arquivo .env do Docker, que tem linhas simples com sintaxe simples VAR=VAL (conforme este link). ideia sendo .env arquivo está comprometido com o repositório e o script de construção pode executá-lo no meu local ou docker-compose pode executá-lo no teste / implantação.

Não existem realmente variáveis ​​de ambiente
https://en.wikipedia.org/wiki/Environment_variable se fizerem parte de
a base do código e não parte do ambiente ...

Na sexta-feira, 28 de junho de 2019 às 14h04 Sudarshan Wadkar [email protected]
escrevi:

Sim, direnv é bom, mas não tenho certeza se será útil com o Docker
Arquivo .env que tem linhas simples com sintaxe VAR = VAL simples (de acordo com este
https://docs.docker.com/compose/env-file/#syntax-rules link.) A ideia
sendo o arquivo .env está comprometido com o repositório e o script de construção pode
executá-lo no meu local ou docker-compose pode executá-lo no staging / deploy.

-
Você está recebendo isto porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/docker/compose/issues/4081?email_source=notifications&email_token=AACHRDCEKOMK2VI3A43QBC3P4XV5BA5CNFSM4CUISSSKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODYZY53A#issuecomment-506695404 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AACHRDF3Q3YOZPHUIUZYEPTP4XV5BANCNFSM4CUISSSA
.

Oh ok.

Gosto de pensar que o arquivo .env transforma em variável de ambiente quando você executa docker-compose up .

Meu caso de uso era usar o mesmo arquivo .env como a fonte da verdade para executar uma instância dev local (possivelmente sem a ajuda de docker-compose ). Então, sim, talvez essas linhas no arquivo .env não sejam realmente variáveis ​​de ambiente, mas com certeza se transformam em uma quando você implanta.

Ainda não vejo como direnv vai ajudar nesse caso.

Outro caso de uso é colocar um comando que gere uma senha atribuindo-o a env var no contêiner.
Dessa forma, a senha não seria gravada em arquivos .env ou docker-compose.yml.

Acho que isso será um grande benefício para muitos casos de uso relacionados à segurança.

+1

+1

+1, seria extremamente útil para definir uid e gid sem complicar demais a solução

`` `
/ _ / \
(oo)

^ <`` `

+1 Eu tenho um caso de uso como mencionado acima para adicionar git branch e commit no arquivo de composição que eventualmente irá para o dockerfile e então será adicionado como uma versão no manifesto do jar construído em um estágio de um processo de compilação do docker de vários estágios .

  gateway:
    image: name
    build:
      context: ./project
      dockerfile: build/Dockerfile
      args:
        - GIT_COMMIT=${$(git rev-list -1 HEAD):-unspecified}
        - GIT_DATE=${$(git log -1 --date=short --pretty=format:%ct):-unspecified}

Portanto, atualmente, para 7 projetos em meu arquivo de composição, tenho que definir ambientes 7x2. Triste.

@ shin- Você poderia reabrir isso como uma solicitação de recurso? Parece que não foi resolvido por boas soluções alternativas e há uma necessidade sólida para isso.

+1 Provavelmente poderia ter conseguido isso de uma maneira diferente, mas eu precisava ativar o motor docker de dentro de um contêiner para reiniciar um contêiner vizinho. No caso em que meu certificado Letsencrypt expirou, mas preciso reiniciar o contêiner NGinx após a renovação. O problema é: como posso informar docker-compose dentro do contêiner qual é o nome do projeto para este grupo de contêineres? PROJECT=(basedir ~+) . Por enquanto, está codificado manualmente :(

+1 para esse pedido de recurso
Outro caso de uso é pegar segredos de um cli / http (por exemplo, cofre, 1Password) e conectá-los ao ambiente.
ie

...
    environment:
      - SERVICE_USERNAME=$(vault kv get -field=username kv/service/credentials)
      - SERVICE_PASSWORD=$(vault kv get -field=password kv/service/credentials)
...

Tenho a mesma necessidade que @rafaelbattesti , exceto que estou usando o lastpass.

...
     environment:
         - TRPASSWD=$(lpass show --password Transmission)
....

+1

+1

@ shin- Você poderia reabrir isso como uma solicitação de recurso? Parece que não foi resolvido por boas soluções alternativas e há uma necessidade sólida para isso.

@ four43 , talvez @ shin- ou outras pessoas não leiam comentários sobre questões fechadas? Vamos abrir outro para chamar a atenção?

A expansão variável no arquivo docker-compose seria um recurso muito útil de se ter ...

+1

@esale - Sim, acho que depende. Pude ver que está fora do escopo deste caso. Não exagere em alguns DSL demais. Nesse ponto, modele o arquivo docker-compose com alguma outra ferramenta? Estamos cruzando as preocupações demais?

Se você estiver usando um arquivo .env, você pode substituir a saída do shell por um comando como este

eval "echo \"$(cat .env.example)\"" > .env

Exemplo de arquivo .env.example

DOCKER_BIN=$(which docker)
DOCKER_COMPOSE_BIN=$(which docker-compose)

Crie o arquivo .env

DOCKER_BIN=/snap/bin/docker
DOCKER_COMPOSE_BIN=/snap/bin/docker-compose
Esta página foi útil?
0 / 5 - 0 avaliações