Coisas que aprendi enquanto escrevia um Dockerfile

Estou escrevendo um Dockerfile para o trabalho que instala o Postgresql e configura um banco de dados. Eu encontrei algumas pegadinhas ao longo do caminho. Aqui está a documentação de meus equívocos e as soluções.

Uma linha VS várias linhas

Originalmente, eu estava usando um comando RUN por linha de shell que queria executar:

Exemplo:

RUN service postgresql start 
RUN su postgres
-c "createuser -d -r -s root"

O problema

Eu queria separar os comandos para otimizar a recriação de outras imagens. Mas sempre recebo o erro de que o postgres não está funcionando. Isso é exatamente porque cada comando RUN é uma camada separada da máquina em execução. Iniciar o postgres em um comando RUN não faz nada porque assim que o próximo comando RUN é alcançado, estou em uma nova VM e não há postgres em execução.

A solução

Comandos de junção que fazem parte de um passo de configuração coeso em uma instrução RUN:
(Observe, obrigado @outrunthewolf por apontar que continuações de linha podem ser usadas para transportar o mesmo comando em várias linhas para facilitar a leitura).

RUN service postgresql start && 
su postgres
-c "createuser -d -r -s root"

sudo VS su

O problema

Os guias online para instalação e configuração do postgres instruem o usuário a executar comandos como sudo, mas isso não funcionará com um Dockerfile porque os comandos estão sendo executados como root e o root não tem acesso ao sudocomando.

A solução

Use para executar comandos como um usuário diferente.su {USER} -c "commands go here"

Um exemplo de Dockerfile

Aqui está um exemplo de Dockerfile que instala o postgresql, cria uma rootfunção e cria um banco de dados chamado accounts.

FROM ubuntu
MAINTAINER
Murphy Randle, murphy@spacemonkey.com

# Install Postgresql deps
RUN apt
-get install -y postgresql postgresql-contrib

# Postgresql setup:
RUN service postgresql start
&& su postgres -c "createuser -d -r -s root" && createdb accounts && service postgresql stop

ENTRYPOINT
["/bin/bash"]