Imagine que você acabou de criar um aplicativo no Phoenix e agora está pronto para compartilhá-lo com o resto do mundo. Você deve estar se perguntando como exatamente navegar no ambiente de publicação e onde publicar seu aplicativo.
Resumindo, você pode usar o Docker para publicar seus projetos em qualquer lugar. Elixir precisa de algumas dependências de tempo de execução, principalmente Erlang, para iniciar o BEAM. Há um Dockerfile excelente disponível na seção "Usando versões para implantação" dos documentos de lançamento do Phoenix, Como consertar o Edge que não atualiza no Windows 11? 8 soluções alternativas podem ser um bom ponto de partida. Neste tutorial, dissecarei este Dockerfile e explicarei o que cada etapa faz, permitindo que você escolha quais partes você gosta e quais você pode precisar alterar para atender às necessidades do seu projeto. vamos começar!
-
começar
-
etapas de construção
-
etapas de tempo de execução
começar
Como teaser, incluirei Node.js e npm neste post, que não estão incluídos no Dockerfile oficial da documentação:
ARG ELIXIR_VERSION=1.14.0 ARG OTP_VERSION=25.0.3 ARG DEBIAN_VERSION=bullseye-20210902-slim ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}" ARG RUNNER_IMAGE= "debian:${DEBIAN_VERSION}"
No código acima, definimos cada etapa separadamente, como corrigir o erro Err_Cache_Miss no Chrome? 9 maneiras fáceis que farão mais sentido posteriormente neste tutorial. Agora, definimos a versão do Elixir que queremos compilar, a versão Erlang OTP que queremos e a imagem do Linux que queremos que seja o carro-chefe.
etapas de construção
Começaremos usando uma imagem do construtor:
FROM ${BUILDER_IMAGE} como construtor # instalar dependências de construção EXECUTAR apt-get update -y && apt-get install -y build-essential git nodejs npm curl \ && apt-get clean && rm -f /var/lib/apt/lists /*_* EXECUTAR curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \ && apt-get install -y nodejs # prepara diretório de compilação WORKDIR /app
O código acima inclui a maioria das dependências de que precisamos, como Node.js, npm e cURL. Mas se precisar de outros, você pode adicioná-los aqui. Lembre-se de que nem toda imagem requer a adição de Node.js, portanto, você pode remover esta etapa, se necessário.
Isso cuida da configuração. De agora em diante é tudo sobre a nossa aplicação:
# instala hex + vergalhão RUN mix local.hex --force && \ mix local.rebar --force # set build ENV ENV MIX_ENV="prod" # instala dependências de mix COPY mix.exs mix.lock ./ RUN mix deps.get --only $MIX_ENV RUN mkdir config # copie os arquivos de configuração em tempo de compilação antes de compilarmos as dependências # para garantir que qualquer alteração relevante na configuração acionará as dependências # a serem recompiladas. COPY config/config.exs config/${MIX_ENV}.exs config/ RUN mix deps.compile COPY priv priv COPY lib lib COPY assets assets WORKDIR assets RUN node --version RUN npm i -g yarn; versão do conjunto de fios estável RUN yarn install WORKDIR ../ # compilar assets RUN mix assets.deploy # Compilar o release RUN mix compile
Primeiro, usamos mix para instalar o Rebar v3 e o Hex. Rebar lida com bibliotecas Erlang nativas, enquanto mix busca nossas dependências Elixir; você pode compará-lo com o npm do Node.js. Em seguida, copiamos nosso mixfile, que representa nossas dependências do projeto, junto com o lockfile e a configuração no código-fonte.
Então, buscamos todas as dependências e as compilamos. Observe que isso compila apenas as dependências, não nossos arquivos de projeto; essas são duas etapas separadas. Finalmente, copiamos nossos arquivos de projeto:
-
priv: migrações e arquivos estáticos
-
lib: nosso código fonte
-
ativos: nosso código JavaScript e CSS
As próximas cinco etapas são opcionais. Se você estiver usando Node.js e npm, mude para a pasta, instale as dependências usando Yarn ou npm e depois mude para .workdir assets
workdir``src/
Neste ponto, podemos implantar nossos ativos, que é uma etapa especial que deixa todos os nossos arquivos JavaScript e CSS prontos para implantação.
Em seguida, compilamos o restante do código-fonte do Elixir, deixando todos os arquivos do projeto prontos para a etapa final de construção (a compilação de lançamento):
# Mudanças em config/runtime.exs não requerem a recompilação do código COPY config/runtime.exs config/ COPY rel rel RUN mix release
Observe como copiamos a configuração do tempo de execução após a etapa de compilação. Este é um bom lembrete de que todas as configurações em todos os outros arquivos de configuração são compiladas na compilação, portanto, não podem ser alteradas neste momento. Porém, como o nome indica, a configuração em tempo de execução é lida em tempo de execução.
A versão RUN mix criará um arquivo de versão que contém tudo o que é necessário para executar o aplicativo.
etapas de tempo de execução
# inicia um novo estágio de construção para que a imagem final contenha apenas # a versão compilada e outras necessidades de tempo de execução FROM ${RUNNER_IMAGE} RUN apt-get update -y && apt-get install -y libstdc++6 openssl libncurses5 locales \ && apt-get clean && rm -f /var/lib/apt/lists/*_* # Defina o local RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 WORKDIR "/app" RUN chown ninguém /app # set runner ENV ENV MIX_ENV="prod" # Copie apenas a versão final de o estágio de construção COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/myapp ./ USUÁRIO ninguém CMD ["/app/bin/servidor"]
Novamente, o código acima foi retirado da documentação oficial do Phoenix, mas vou esclarecer novamente onde o comentário parou.
Aqui nos referimos ao anterior, mas desta vez pegamos apenas a imagem do Linux. Isso por si só torna nossas imagens Docker em tempo de execução surpreendentemente pequenas. ARGS
Outro benefício de nossa configuração inicial de instalação, pacote misto, etc. é que para executar nosso aplicativo Elixir, precisamos apenas dos binários criados a partir de nossas etapas no final da seção de construção, reduzindo o tamanho da imagem de construção em particular. lançamento do node_modules``mix
Permitimos que todos acessem nosso diretório de aplicativos, alteremos nosso usuário para um usuário estritamente restrito e executemos o aplicativo.
para concluir
Embora as etapas deste artigo sejam longas, basicamente se resumem ao seguinte comando único que pode ser executado:
> misture phx.gen.release --docker
O código acima irá gerar um Dockerfile semelhante ao que abordamos neste artigo, mas com algumas diferenças. O projeto Phoenix padrão não usa Node.js, portanto não inclui as etapas do Node.js que incluí neste Dockerfile.
Este Dockerfile é usado como ponto de partida para implantação de aplicações Phoenix e neste artigo mostro como alterá-lo para atender às suas necessidades. Neste exemplo, incluímos etapas npm e Node.js. A partir daqui, tudo o que você precisa fazer é brincar e descobrir quais detalhes você precisa.
O legal de ter imagens separadas do gerador e do tempo de execução é que não há custo real em ter muitos dados na imagem do gerador. Sim, isso retarda a construção, mas a maioria dessas coisas pode ser armazenada em cache no pipeline e armazenada automaticamente em cache local. Independentemente disso, sua imagem de tempo de execução será pequena e lançada rapidamente, já que é uma distribuição Linux básica.