DEV Community

Zoey de Souza Pessanha
Zoey de Souza Pessanha

Posted on

Ambiente de desevolvimento Elixir/Phoenix com Nix

Nos artigos anteriores, escrevi uma breve introdução ao Nix, apresentei algumas vantagens e exemplos,
e a especificação da sintaxe da linaguagem além de apresentar alguns contras e limitações dessa ferramenta!

Neste artigo irei mostrar um exemplo de configuração para um ambiente de desenvolvimento de projetos na linguagem
Elixir com o mix e também suporte ao framework Phoenix

Requisitos

Os únicos requisitos para seguir este tutorial é ter um conhecimento brévio sobre o ecossistema Elixir e
possuir o gerenciador de pacotes Nix instalado no seu sistema.

Caso esteja usando a distribuição NixOS, o gerenciador de pacotes já estará disponível.

Projeto base criado com o mix

O mix é a ferramenta de contrução utilizada no ecossistema Elixir para compilar seu projeto,
realizar tarefas mix, rodar os testes de sua apliação dentre outras funcionalidades.

Para torná-lo acessível num ambiente isolado, crie um arquivo shell.nix, com esse conteúdo:

{ pkgs ? import <nixpkgs> {} }: with pkgs; let elixirDrv = elixir.override { version = "1.11.4"; rev = "308255bda81e7f76f9bec838cef033e8e869981b"; sha256 = "1y8fbhli29agf84ja0fwz6gf22a46738b50nwy26yvcl2n2zl9d8"; minimumOTPVersion = "23"; }; in mkShell { name = "exemplo_dev"; buildInputs = [ readline elixirDrv ] shellHook = ''  mkdir -p .nix-mix  mkdir -p .nix-hex  export MIX_HOME=$PWD/.nix-mix  export HEX_HOME=$PWD/.nix-hex  export PATH=$MIX_HOME/bin:$PATH  export PATH=$HEX_HOME/bin:$PATH  export LANG=en_US.UTF-8  export ERL_AFLAGS="-kernel shell_history enabled"  export ERL_LIBS=$HEX_HOME/lib/erlang/lib  ''; } 
Enter fullscreen mode Exit fullscreen mode

Com isso, execute nix-shell ou nix-shell <caminho/para/shell.nix> e você poderá
utilizar o mix!

Vamos desconstruir esse arquivo:

{ pkgs ? import <nixpkgs> {} }: with pkgs; 
Enter fullscreen mode Exit fullscreen mode

No começo do arquivo importamos os pacotes a aprtir do repositório nixpkgs e trazemos todas as opções desse
módulo para o escopo léxico atual.

Já dentro do bloco let...in, sobrescrevo a versão do pacote da linguagem Elixir, que atualmente está na versão 1.10.4
no canal estável:

elixirDrv = elixir.override { version = "1.11.4"; rev = "308255bda81e7f76f9bec838cef033e8e869981b"; sha256 = "1y8fbhli29agf84ja0fwz6gf22a46738b50nwy26yvcl2n2zl9d8"; minimumOTPVersion = "23"; }; 
Enter fullscreen mode Exit fullscreen mode

Essa expressão pode ser usada para utilizar qualquer versão da linguagem. Existem versões anteriores já envelopadas
no reposiório nixpkgs como os pacotes elixir_1_9 e elixir_1_7.

Dentro da derivção especial mkShell, definimos um nome para esse ambiente e depois definimos a opção buildInputs,
que presenta quais são as dependências desse ambiente a ser criado:

buildInputs = [ readline elixirDrv ] 
Enter fullscreen mode Exit fullscreen mode

E por último declaramos um pequeno script que será executado antes do ambiente ser criado:

shellHook = ''  mkdir -p .nix-mix  mkdir -p .nix-hex  export MIX_HOME=$PWD/.nix-mix  export HEX_HOME=$PWD/.nix-hex  export PATH=$MIX_HOME/bin:$PATH  export PATH=$HEX_HOME/bin:$PATH  export LANG=en_US.UTF-8  export ERL_AFLAGS="-kernel shell_history enabled"  export ERL_LIBS=$HEX_HOME/lib/erlang/lib ''; 
Enter fullscreen mode Exit fullscreen mode

Neste exemplo, criamos dois diretórios para abrigar as instalações locais
do mix e hex, tornamos disponmíveis os seus executáveis, e definimos duas
variáveis ambiente referentes à BEAM:

  1. ERL_AFLAGS: o conteúdo dessa variáveis é adicionado no começo do comando erl
  2. ERL_LIBS: necessária caso você já possua uma instalação local de elixir, suprimindo os avisos que a biblioteca padrão está sendo redefinida durante a compilação

Projetos Phoenix

Já para projetos Phoenix, devemos realizar algumas mudanças no arquivo shell.nix.

Phoenix + PostgreSQL

A primeira mudança é na opção buildInputs, onde adicionamos algumas dependência para compilação de
algumas dependências do projeto dentre outros utilitários:

buildInputs = [ gnumake gcc readline openssl zlib libxml2 curl libiconv # minha versão do pacote `elixir` elixirDrv glibcLocales nodejs-12_x yarn postgresql gtk-engine-murrine ] ++ lib.optional stdenv.isLinux [ inotify-tools # dependência do GTK para usar o observer gtk-engine-murrine ] ++ lib.optionals stdenv.isDarwin (with darwin.apple_sdk.frameworks; [ CoreFoundation CoreServices ]); 
Enter fullscreen mode Exit fullscreen mode

A segunda alteração é no script inicial do ambiente, onde definimos algumas váriaveis ambiente
para configuração do servidor do PostgreSQL e criamos um usuário padrão.

Para isso, adicione os seguintes comandos na opção shellHook:

export PGHOST=$PWD/.postgres export PGDATA=$PGHOST/data export PGLOG=$PGHOST/postgres.log export PGPASSWORD=postgres if [ ! -d $PGDATA ]; then echo 'Initializing postgresql database...' initdb --auth=trust --no-locale --encoding=UTF8 >/dev/null fi # inicializando o servidor pg_ctl start -l $PGLOG -o "--unix_socket_directories='$PGHOST'" # verifica se existe um usuário padrão, caso contrário ele é criado psql -d postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='postgres'" | grep -q 1 \ || createuser -s postgres # assim que você sair do ambiente criado pelo `nix-shell` # o servidor do postgres será desligado  finish() { pg_ctl -D $PGDATA stop } trap finish EXIT 
Enter fullscreen mode Exit fullscreen mode

O código completo desta expressão Nix está disponível neste gist.

Phoenix + MariaDB/MySQL

Caso você esteja usando o MariaDB ou MySQL como SGBD, apenas altere a útilma parte do shellHook, removendo
as opções relacionadas ao PostgreSQL e adicionando essas linhas:

export MYSQL_BASEDIR=${pkgs.mariadb} export MYSQL_HOME=$PWD/mysql export MYSQL_DATADIR=$MYSQL_HOME/data export MYSQL_UNIX_PORT=$MYSQL_HOME/mysql.sock export MYSQL_PID_FILE=$MYSQL_HOME/mysql.pid mysql_install_db --datadir=$MYSQL_DATADIR --basedir=$MYSQL_BASEDIR --pid-file=$MYSQL_PID_FILE mysqld --datadir=$MYSQL_DATADIR --pid-file=$MYSQL_PID_FILE --socket=$MYSQL_UNIX_PORT & export MYSQL_PID=$! finish() { mysqladmin --socket=$MYSQL_UNIX_PORT shutdown kill $MYSQL_PID wait $MYSQL_PID } trap finish EXIT 
Enter fullscreen mode Exit fullscreen mode

Conclusão

Utilizando essas derivações, é possível configurar um ambiente de densenvolvimento totalmente reproduzível
e estável em poucos minutos!

Vale lembrar que esta derivação é plenamente editável e pode ser adaptada para outros tipo de ambientes,
por exemplo aplicações Rails, Django ou mesmo Express ou AdonisJS.

Este post foi publicado com minha ferramenta de linha de comando devit!
Você pode encontrar instruções para instalação neste link.

Top comments (0)