One place for hosting & domains

      Usando

      Como implantar o Laravel 7 e o MySQL no Kubernetes usando o Helm


      O autor selecionou a Diversity in Tech Fund​​​​​ para receber uma doação como parte do programa Write for DOnations.

      Introdução

      O Laravel é um dos frameworks de aplicação PHP de código aberto mais populares atualmente. Ele é comumente implantado com um banco de dados MySQL, mas pode ser configurado para usar uma variedade de opções de armazenamento de dados de backend. O Laravel se orgulha de tirar proveito de muitos dos recursos modernos do PHP e do extenso ecossistema de pacotes.

      O Kubernetes é uma plataforma de orquestração de contêiner que pode ser hospedada em clusters Kubernetes da DigitalOcean para retirar grande parte do trabalho de administração da instalação e operação de contêineres em produção. O Helm é um gerenciador de pacotes do Kubernetes que facilita a configuração e instalação de serviços e pods no Kubernetes.

      Neste guia, você irá criar uma aplicação Laravel PHP, compilar sua aplicação dentro de uma imagem Docker, e implantar essa imagem em um cluster Kubernetes da DigitalOcean usando o LAMP Helm chart. Em seguida, você irá configurar um controlador Ingress para adicionar SSL e um nome de domínio personalizado à sua aplicação. Quando concluída, você terá uma aplicação Laravel funcionando conectada a um banco de dados MySQL que está em execução em um cluster do Kubernetes.

      Pré-requisitos

      • O Docker instalado na máquina a partir da qual você irá acessar seu cluster. Você pode encontrar instruções sobre como fazer a instalação do Docker para a maioria das distribuições Linux aqui ou no site do Docker para outros sistemas operacionais.
      • Uma conta do Docker Hub para armazenar as imagens do Docker que você criará neste tutorial.
      • Um cluster Kubernetes 1.17+ na DigitalOcean com sua conexão configurada como o kubectl padrão. Para aprender como criar um cluster Kubernetes na DigitalOcean, consulte o Kubernetes Quickstart. Para aprender como se conectar ao cluster, consulte How to Connect to a DigitalOcean Kubernetes Cluster.
      • O gerenciador de pacotes Helm 3 instalado em sua máquina local. Complete o primeiro passo e adicione o repositório stable do segundo passo do tutorial How To Install Software on Kubernetes Clusters with the Helm 3 Package Manager.
      • Um nome de domínio totalmente registrado com um registro A disponível. Este tutorial utilizará o your_domain durante todo o processo. Você pode comprar um nome de domínio em Namecheap, obter um gratuitamente em Freenom ou usar o registrado de domínios de sua escolha. No momento, não se preocupe em associar o registro A do seu domínio a um IP. Quando você chegar no Passo 5 e seu controlador Ingress estiver pronto, você irá conectar your_domain ao IP adequado.

      Passo 1 — Criando uma nova aplicação Laravel

      Neste passo, você irá usar o Docker para criar uma nova aplicação Laravel 7, mas você deve ser capaz de seguir o mesmo processo com uma aplicação Laravel existente que usa o MySQL como banco de banco de dados de backend. A nova aplicação que você compilar irá verificar se o Laravel está conectado ao banco de dados e exibirá o nome do banco de dados.

      Primeiro, vá para seu diretório home e crie uma nova aplicação Laravel usando um contêiner Docker composer:

      • cd ~
      • docker run --rm -v $(pwd):/app composer create-project --prefer-dist laravel/laravel laravel-kubernetes

      Depois que o contêiner estiver pronto e todos os pacotes do Composer estiverem instalados, você deve ver uma nova instalação do Laravel em seu diretório atual chamada laravel-kubernetes/. Navegue até essa pasta:

      Você executará o resto dos comandos deste tutorial a partir daqui.

      O objetivo desta aplicação é testar a conexão do seu banco de dados e exibir seu nome no seu navegador. Para testar a conexão do banco de dados, abra o arquivo ./resources/views/welcome.blade.php em um editor de texto:

      • nano ./resources/views/welcome.blade.php

      Encontre a seção <div class="links">...</div> e substitua seu conteúdo pelo seguinte:

      ./resources/views/welcome.blade.php

      ...
      <div class="links">
         <strong>Database Connected: </strong>
          @php
              try {
                  DB::connection()->getPDO();
                  echo DB::connection()->getDatabaseName();
                  } catch (Exception $e) {
                  echo 'None';
              }
          @endphp
      </div>
      ...
      

      Salve e feche o arquivo.

      Essa é toda a personalização que você precisará fazer na aplicação Laravel padrão para este tutorial. Uma vez concluído, este breve trecho de PHP irá testar sua conexão com o banco de dados e exibirá o nome do banco de dados na tela de splash do Laravel em seu navegador Web.

      No próximo passo, você irá usar o Docker para compilar uma imagem contendo esta aplicação Laravel e o Docker Compose para testar se ele funciona localmente e se conecta a um banco de dados MySQL.

      Passo 2 — Conteinerizando sua aplicação Laravel

      Agora que você criou uma nova aplicação Laravel, você precisará compilar seu código dentro de uma imagem Docker e então testar a imagem com o Docker Compose. Embora o objetivo deste tutorial seja implantar sua aplicação em um cluster Kubernetes, o Docker Compose é uma maneira conveniente de testar sua imagem e configuração do Docker localmente antes de executá-la na nuvem. Este loop de feedback rápido pode ser útil para fazer e testar pequenas mudanças.

      Primeiro, usando o nano ou seu editor de texto preferido, crie um arquivo na raiz da sua aplicação Laravel chamado Dockerfile:

      Adicione o conteúdo a seguir: O Docker irá usar este arquivo para compilar seu código em uma imagem:

      ./Dockerfile

      FROM php:7.4-apache
      
      # Install packages
      RUN apt-get update && apt-get install -y 
          git 
          zip 
          curl 
          sudo 
          unzip 
          libicu-dev 
          libbz2-dev 
          libpng-dev 
          libjpeg-dev 
          libmcrypt-dev 
          libreadline-dev 
          libfreetype6-dev 
          g++
      
      # Apache configuration
      ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
      RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
      RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
      RUN a2enmod rewrite headers
      
      # Common PHP Extensions
      RUN docker-php-ext-install 
          bz2 
          intl 
          iconv 
          bcmath 
          opcache 
          calendar 
          pdo_mysql
      
      # Ensure PHP logs are captured by the container
      ENV LOG_CHANNEL=stderr
      
      # Set a volume mount point for your code
      VOLUME /var/www/html
      
      # Copy code and run composer
      COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
      COPY . /var/www/tmp
      RUN cd /var/www/tmp && composer install --no-dev
      
      # Ensure the entrypoint file can be run
      RUN chmod +x /var/www/tmp/docker-entrypoint.sh
      ENTRYPOINT ["/var/www/tmp/docker-entrypoint.sh"]
      
      # The default apache run command
      CMD ["apache2-foreground"]
      

      Salve e feche o arquivo.

      Este Dockerfile começa com a imagem Docker PHP 7.4 Apache encontrada no Docker Hub, em seguida, instala vários pacotes Linux que são comumente exigidos pelas aplicações Laravel. Em seguida, ele cria arquivos de configuração do Apache e habilita reescritas de cabeçalho. O Dockerfile instala várias extensões PHP comuns e adiciona uma variável de ambiente para garantir que os logs do Laravel sejam transmitidos ao contêiner via stderr. Isso permitirá que você veja os logs do Laravel fazendo um tail dos logs do Docker Compose ou do Kubernetes.

      Finalmente, o Dockerfile copia todo o código em sua aplicação Laravel para /var/www/tmp e instala as dependências do Composer. Em seguida, ele define um ENTRYPOINT, mas você precisará criar esse arquivo, o que faremos a seguir.

      No diretório raiz do seu projeto, crie um novo arquivo chamado docker-entrypoint.sh. Este arquivo será executado quando o seu contêiner for executado localmente ou no cluster Kubernetes, e ele irá copiar seu código de aplicação Laravel a partir do diretório /var/www/tmp para /var/www/html onde o Apache será capaz de apresentá-lo.

      • nano ./docker-entrypoint.sh

      Agora adicione o seguinte script:

      ./docker-entrypoint.sh

      #!/bin/bash
      
      cp -R /var/www/tmp/. /var/www/html/
      chown -R www-data:www-data /var/www/html
      
      exec "$@"
      

      A linha final, exec "$@" instrui o shell a executar qualquer comando que seja passado como um argumento de entrada a seguir. Isso é importante porque você quer que o Docker continue executando o comando Apache run (apache2-foreground) após este script ser executado. Salve e feche o arquivo.

      Em seguida, crie um arquivo .dockerignore no diretório raiz da sua aplicação. Este arquivo irá garantir que quando você compilar sua imagem Docker ela não ficará poluída com pacotes ou arquivos de ambiente que não devem ser copiados para ela:

      ./.dockerignore

      .env
      /vendor
      

      Salve e feche o arquivo.

      O último arquivo que você precisa criar antes que você possa executar sua aplicação localmente usando o Docker Compose é um arquivo docker-compose.yml. No entanto, durante a configuração deste arquivo YAML, você precisará inserir o APP_KEY que o Laravel gerou durante a instalação. Encontre isso abrindo e pesquisando o arquivo . /.env, ou executando os seguintes comandos cat e grep:

      Você verá uma saída como esta:

      Output

      APP_KEY=base64:0EHhVpgg ... UjGE=

      Copie sua chave para sua área de transferência. Certifique-se de incluir o prefixo base64: Agora crie o arquivo docker-compose.yml no diretório raiz da sua aplicação:

      • nano ./docker-compose.yml

      Aqui incluiremos a imagem PHP da sua aplicação Laravel, bem como um contêiner MySQL para executar o seu banco de dados. Adicione o conteúdo a seguir:

      ./docker-compose.yml

      version: '3.5'
      services:
        php:
          image: your_docker_hub_username/laravel-kubernetes:latest
          restart: always
          ports:
            - 8000:80
          environment:
            - APP_KEY="your_laravel_app_key"
            - APP_ENV=local
            - APP_DEBUG=true
            - DB_PORT=3306
            - DB_HOST=mysql
            - DB_DATABASE
            - DB_USERNAME
            - DB_PASSWORD
        mysql:
          image: mysql:5.7
          restart: always
          environment:
            - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
            - MYSQL_DATABASE=${DB_DATABASE}
            - MYSQL_USER=${DB_USERNAME}
            - MYSQL_PASSWORD=${DB_PASSWORD}
      

      Use a variável APP_KEY que você copiou para sua área de transferência para a variável your_laravel_app_key e use seu nome de usuário do Docker Hub para a variável your_docker_hub_username. Salve e feche o arquivo.

      Você irá criar a primeira imagem localmente usando o docker build. A segunda imagem é a imagem Docker oficial do MySQL disponível no Docker Hub. Ambos exigem várias variáveis de ambiente, que você irá incluir quando você executar os contêineres.

      Para compilar a imagem Docker que contém sua aplicação Laravel, execute o seguinte comando. Certifique-se de substituir your_docker_hub_username pelo nome de usuário ou nome de sua equipe no Docker Hub onde essa imagem será armazenada:

      • docker build -t your_docker_hub_username/laravel-kubernetes:latest .

      Em seguida, você pode executar os dois contêineres com o Docker Compose com as credenciais de banco de dados necessárias:

      • DB_ROOT_PASSWORD=rootpassword DB_DATABASE=local_db DB_USERNAME=admin DB_PASSWORD=password docker-compose up -d

      As quatro variáveis de ambiente usadas aqui (DB_ROOT_PASSWORD, DB_DATABASE, DB_USERNAME, DB_PASSWORD) podem ser modificadas se você quiser, mas uma vez que você está testando sua aplicação somente localmente, você não precisa se preocupar em protegê-las ainda.

      Pode demorar até 30 segundos para que seu banco de dados MySQL inicialize e os contêineres estejam prontos. Depois que eles etiverem prontos, você pode visualizar sua aplicação Laravel em sua máquina em localhost:8000.

      The Laravel application running locally using Docker Compose

      Sua aplicação PHP irá se conectar ao seu banco de dados MySQL. Após uma conexão bem-sucedida, o texto “Database Connected: local_db” irá aparecer sob o logotipo do Laravel.

      Agora que você testou sua imagem Docker localmente usando o Docker Compose, você pode desligar os contêineres executando docker-compose down:

      Na próxima seção, você irá enviar sua imagem Docker para o Docker Hub para que seu Helm chart possa utilizá-la para implantar a aplicação no cluster Kubernetes.

      Passo 3 — Enviando sua imagem Docker para o Docker Hub

      O LAMP Helm Chart que você irá usar para implantar seu código no Kubernetes requer que seu código esteja disponível em um registro de contêiner. Embora você possa enviar sua imagem para um registro privado ou auto-hospedado, para os propósitos deste tutorial, você irá usar um registro Docker gratuito e disponível publicamente no Docker Hub.

      Acesse sua conta no Docker Hub usando seu navegador Web e então crie um novo repositório chamado laravel-kubernetes.

      Creating a new repository on Docker Hub

      Em seguida, se você não tiver conectado ao Docker Hub a partir de sua máquina local, você precisará fazer login no Docker Hub. Você pode fazer isso através da linha de comando:

      • docker login -u your_docker_hub_username

      Digite suas credenciais de login quando solicitado. Isso normalmente só precisa ser feito uma vez por máquina, pois o Docker irá salvar suas credenciais em ~/.docker/config.json em seu diretório home.

      Finalmente, envie sua imagem para o Docker Hub:

      • docker push your_docker_hub_username/laravel-kubernetes:latest

      Pode demorar alguns minutos para fazer upload da sua aplicação dependendo da velocidade da sua conexão, mas uma vez que o Docker tiver feito, você verá um digest hash final e o tamanho da sua imagem no terminal. Eles se parecerão com isso:

      Output

      latest: digest: sha256:df4bdeda91484c8c26a989b13b8f27ab14d93ab2e676e3c396714cb3811c4086 size: 4918

      Agora que sua aplicação Laravel está conteinerizada e você enviou uma imagem para o Docker Hub, use a imagem em uma implantação do Helm Chart ou do Kubernetes. No próximo passo, você irá definir valores personalizados com base no LAMP Helm Chart e implantá-los em seu cluster Kubernetes.na DigitalOcean.

      O Helm fornece uma variedade de Charts para ajudá-lo a configurar aplicações Kubernetes usando combinações predefinidas de ferramentas. Embora você possa escrever seus próprios arquivos de serviço do Kubernetes para realizar uma implantação semelhante, você verá nesta seção que usar um Helm Chart irá exigir muito menos configuração.

      Primeiro, você precisará de um diretório para armazenar todos os seus arquivos de configuração do Helm. Crie um novo diretório na raiz do seu projeto Laravel chamado helm/:

      Dentro do diretório helm/, você irá criar dois novos arquivos: values.yml e secrets.yml. Primeiro, crie e abra values.yml:

      O arquivo values.yml irá incluir opções de configuração não secretas que irão substituir os valores padrão no LAMP Helm chart. Adicione as seguintes configurações, certificando-se de substituir your_docker_hub_username pelo seu próprio nome de usuário:

      ./helm/values.yml

      php:
        repository: "your_docker_hub_username/laravel-kubernetes"
        tag: "latest"
        fpmEnabled: false
        envVars:
          - name: APP_ENV
            value: production
          - name: APP_DEBUG
            value: false
          - name: DB_PORT
            value: 3306
          - name: DB_HOST
            value: localhost
      

      Salve e feche o arquivo.

      Agora crie um arquivo secrets.yml:

      secrets.yml não será verificado no controle de versão. Ele irá conter informações de configuração confidenciais como a senha do seu banco de dados e a chave da aplicação Laravel. Adicione as seguintes configurações, ajustando-as conforme necessário para corresponder às suas credenciais:

      ./helm/secrets.yml

      mysql:
        rootPassword: "your_database_root_password"
        user: your_database_user
        password: "your_database_password"
        database: your_database_name
      
      php:
        envVars:
          - name: APP_KEY
            value: "your_laravel_app_key"
          - name: DB_DATABASE
            value: your_database_name
          - name: DB_USERNAME
            value: your_database_user
          - name: DB_PASSWORD
            value: "your_database_password"
      

      Certifique-se de usar combinações de nome de usuário e senha fortes para seu banco de dados de produção, e use a mesma your_laravel_app_key como acima, ou abra uma nova janela de terminal e gere uma nova chave executando o seguinte comando. Você pode então copiar o novo valor que o Laravel definir em seu arquivo .env:

      • docker run --rm -v $(pwd):/app php:cli php /app/artisan key:generate

      Salve e feche o arquivo secrets.yml.

      Em seguida, para evitar que seu arquivo secrets.yml seja incorporado na imagem Docker ou salvo no controle de versão, certifique-se de adicionar a seguinte linha a ambos os arquivos .dockerignore e .gitignore. Abra e acrescente /helm/secrets.yml a cada arquivo, ou execute o seguinte comando para adicionar ambos:

      • echo '/helm/secrets.yml' >> ./.dockerignore && echo '/helm/secrets.yml' >> ./.gitignore

      Agora que você criou arquivos de configuração do Helm para sua aplicação e a imagem Docker, você pode instalar este Helm chart como uma nova versão em seu cluster Kubernetes. Instale seu chart a partir do diretório raiz da sua aplicação:

      • helm install laravel-kubernetes -f helm/values.yml -f helm/secrets.yml stable/lamp

      Você verá uma saída como esta:

      Output

      NAME: laravel-kubernetes LAST DEPLOYED: Mon May 18 13:21:20 2020 NAMESPACE: default STATUS: deployed REVISION: 1

      Sua aplicação irá demorar um ou dois minutos para se tornar disponível, mas você pode executar este comando para monitorar os serviços Kubernetes em seu cluster:

      Procure pelo nome da sua aplicação:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) laravel-kubernetes-lamp LoadBalancer your_cluster_ip your_external_ip 80:32175/TCP,3306:32243/TCP

      Quando seu novo serviço laravel-kubernetes-lamp exibir um endereço IP sob EXTERNAL-IP, você pode visitar your_external_ip para ver a aplicação em execução no seu cluster Kubernetes. Sua aplicação irá se conectar ao seu banco de dados e você verá o nome do banco de dados abaixo do logotipo do Laravel, como você fez ao executar sua aplicação localmente no Docker Compose.

      The Laravel application running on Kubernetes using the LAMP Helm chart

      Executar uma aplicação Web em um endereço IP desprotegido pode não ser um problema para uma prova de conceito, mas seu site não está pronto para a produção sem um certificado SSL e um nome de domínio personalizado. Antes de configurar isso no próximo passo, desinstale seu release através da linha de comando:

      • helm delete laravel-kubernetes

      No próximo passo, você irá expandir esta primeira configuração do Helm para adicionar um controlador Ingress, um certificado SSL e um domínio personalizado à sua aplicação Laravel.

      Passo 5 — Adicionando um controlador Ingress e SSL ao seu cluster Kubernetes

      No Kubernetes, um controlador Ingress é responsável por expor os serviços da sua aplicação à internet. No passo anterior, o LAMP Helm chart criou um balanceador de carga da DigitalOcean e expôs sua aplicação diretamente através do endereço IP do balanceador.

      Você pode terminar o SSL e seu nome de domínio diretamente no balanceador de carga, mas como você está trabalhando no Kubernetes, pode ser mais conveniente gerenciar tudo isso no mesmo lugar. Para saber muito mais sobre controladores Ingress e detalhes sobre os seguintes passos, leia o tutorial How To Set Up an Nginx Ingress on DigitalOcean Kubernetes Using Helm.

      O LAMP Helm chart inclui uma opção de configuração para suportar o Ingress. Abra seu arquivo helm/values.yml:

      Agora, adicione as linhas a seguir:

      ./helm/values.yml

      ...
      # Use Ingress Controller
      service:
        type: ClusterIP
        HTTPPort: 80
      ingress:
        enabled: true
        domain: your_domain
      

      Isso instrui sua implantação a não instalar um balanceador de carga e, em vez disso, expor a aplicação à porta 80 do cluster Kubernetes, onde o controlador Ingress irá expô-la à internet. Salve e feche o arquivo values.yml.

      Agora, execute o comando helm install que você executou anteriormente para que sua aplicação Laravel seja executada novamente. Certifique-se de executar o comando a partir do diretório raiz da sua aplicação:

      • helm install laravel-kubernetes -f helm/values.yml -f helm/secrets.yml stable/lamp

      Em seguida, instale o controlador nginx-ingress em seu cluster Kubernetes usando o controlador Ingress Nginx mantido pelo Kubernetes:

      • helm install nginx-ingress stable/nginx-ingress --set controller.publishService.enabled=true

      Depois da instalação, você verá uma saída como esta:

      Output

      NAME: nginx-ingress LAST DEPLOYED: Mon May 18 13:28:34 2020 NAMESPACE: default STATUS: deployed REVISION: 1

      Você também precisa de um recurso ou Resource Ingress para expor sua implantação da aplicação Laravel. Crie um novo arquivo no diretório raiz da sua aplicação chamado ingress.yml:

      Este arquivo define o host da sua aplicação, o gerenciador de certificados SSL e o serviço de backend e o nome da porta. Adicione as seguintes configurações, substituindo your_domain pelo domínio da sua escolha:

      ./ingress.yml

      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress
      metadata:
        name: laravel-kubernetes-ingress
        annotations:
          kubernetes.io/ingress.class: nginx
          cert-manager.io/cluster-issuer: letsencrypt-prod
      spec:
        tls:
          - hosts:
              - your_domain
            secretName: laravel-kubernetes-tls
        rules:
          - host: your_domain
            http:
              paths:
                - backend:
                    serviceName: laravel-kubernetes-lamp
                    servicePort: 80
      

      Salve e feche o arquivo.

      Em seguida, você deve instalar o Cert-Manager e criar um emissor que lhe permitirá criar certificados SSL de produção usando o Let’s Encrypt. O Cert-Manager requer Definições de Recursos Personalizadas que você pode aplicar a partir do repositório Cert-Manager usando a linha de comando:

      • kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.15.0/cert-manager.crds.yaml

      Isto irá criar uma série de recursos do Kubernetes que serão exibidos na linha de comando:

      Output

      customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io create

      O Cert-Manager também requer um namespace para isolá-lo em seu cluster Kubernetes:

      • kubectl create namespace cert-manager

      Você verá esta saída:

      Output

      namespace/cert-manager created

      Como o Cert-Manager do Jetstack não é um dos charts mantidos pelo Kubernetes, você precisará adicionar o repositório Helm do Jetstack também. Execute o seguinte comando para torná-lo disponível no Helm:

      • helm repo add jetstack https://charts.jetstack.io

      Uma adição bem sucedida irá exibir o seguinte:

      Output

      "jetstack" has been added to your repositories

      Agora você está pronto para instalar o Cert-Manager no namespace cert-manager em seu cluster Kubernetes:

      • helm install cert-manager --version v0.15.0 --namespace cert-manager jetstack/cert-manager

      Quando terminar, você verá um resumo da implantação como este:

      Output

      NAME: cert-manager LAST DEPLOYED: Mon May 18 13:32:08 2020 NAMESPACE: cert-manager STATUS: deployed REVISION: 1

      O último arquivo que você precisará adicionar ao diretório raiz da sua aplicação Laravel é um arquivo de configuração do Kubernetes production_issuer.yml. Crie o arquivo:

      • nano ./production_issuer.yml

      Agora, adicione o seguinte:

      apiVersion: cert-manager.io/v1alpha2
      kind: ClusterIssuer
      metadata:
        name: letsencrypt-prod
      spec:
        acme:
          # Email address used for ACME registration
          email: your_email_address
          server: https://acme-v02.api.letsencrypt.org/directory
          privateKeySecretRef:
            # Name of a secret used to store the ACME account private key
            name: letsencrypt-prod-private-key
          # Add a single challenge solver, HTTP01 using nginx
          solvers:
            - http01:
                ingress:
                  class: nginx
      

      Salve e feche o arquivo.

      O Let’s Encrypt irá enviar para your_email_address quaisquer avisos importantes e avisos de expiração, então certifique-se de adicionar um endereço que você irá verificar regularmente. Salve este arquivo e crie um novo recurso tanto para o seu recurso Ingress quanto para o emissor de produção em seu cluster Kubernetes:

      • kubectl create -f ingress.yml
      • kubectl create -f production_issuer.yml

      Finalmente, atualize os registros DNS do seu nome de domínio para apontar um registro A para o endereço IP do seu balanceador de carga. Para encontrar o endereço IP para seu controlador Ingress digite:

      • kubectl get service nginx-ingress-controller

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-ingress-controller LoadBalancer your_cluster_ip your_external_ip 80:30187/TCP,443:31468/TCP 6m10s

      Use o endereço your_external_ip como o endereço IP para seu registro A no DNS. O processo para atualizar seus registros DNS varia dependendo do local onde você gerencia seus nomes de domínio e hospedagem DNS, mas se você estiver usando a DigitalOcean você pode buscar referência em nosso guia How to Manage DNS Records.

      Depois que seus registros de DNS atualizarem e seu certificado SSL for gerado, sua aplicação estará disponível em your_domain e o SSL estará habilitado.

      The Laravel application with SSL termination and a custom domain name

      Embora sua aplicação PHP e seu banco de dados já estejam conectados, você ainda precisará executar as migrações de banco de dados. No último passo, você verá como executar comandos Artisan em seu pod Kubernetes para realizar migrações de banco de dados e outras tarefas comuns de manutenção.

      Passo 6 — Executando comandos remotos

      Embora sua aplicação Laravel esteja executando e esteja conectada ao banco de dados MySQL no Kubernetes, há várias operações comuns que você deve executar em uma nova instalação do Laravel. Uma tarefa comum que você deve realizar são as migrações de banco de dados.

      Antes que você possa executar um comando Artisan em sua aplicação Laravel, você precisa saber o nome do pod que está executando seu contêiner da aplicação Laravel. Usando a linha de comando, você pode visualizar todos os pods em seu cluster Kubernetes:

      Você verá uma saída como esta:

      Output

      NAME READY STATUS RESTARTS AGE laravel-kubernetes-lamp-77fb989b46-wczgb 2/2 Running 0 16m

      Selecione o pod para sua implantação laravel-kubernetes-lamp-.... Certifique-se de usar o nome em sua saída e não o que está listado acima. Agora, você pode executar o kubectl exec nele. Por exemplo, execute uma migração de banco de dados usando o comando artisan migrate. Você irá adicionar a flag --force porque você está executando o pod em produção:

      • kubectl exec laravel-kubernetes-lamp-77fb989b46-wczgb -- php artisan migrate --force

      Este comando irá produzir uma saída:

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.16 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.05 seconds)

      Agora, você implantou com sucesso o Laravel 7 e o MySQL no Kubernetes e realizou uma tarefa essencial de manutenção de banco de dados.

      Conclusão

      Neste tutorial, você aprendeu como conteinerizar uma aplicação PHP Laravel, conectar-se a um banco de dados MySQL, enviar uma imagem Docker contendo o seu código para o Docker Hub, e então usar um Helm chart para implantar essa imagem em um cluster Kubernetes da DigitalOcean. Finalmente, você adicionou SSL e um nome de domínio personalizado e aprendeu como executar ferramentas de linha de comando em seus pods em execução.

      O Kubernetes e o Helm lhe oferecem uma série de vantagens em relação à tradicional hospedagem de pilhas LAMP: escalabilidade, a capacidade de alternar serviços sem precisar fazer login diretamente no seu servidor, ferramentas para realizar atualizações contínuas e controlar seu ambiente de hospedagem. Dito isso, a complexidade de inicialmente conteinerizar e configurar sua aplicação torna a barreira para começar bastante alta. Com este guia como ponto de partida, implantar o Laravel no Kubernetes torna-se mais acessível. A partir daqui você pode considerar aprender mais sobre o poder do Laravel ou adicionar ferramentas de monitoramento ao Kubernetes como o Linkerd, que você pode instalar manualmente com nosso guia ou com um droplet 1-Click da DigitalOcean.



      Source link

      Como criar uma pool de armazenamento com redundância usando o GlusterFS no Ubuntu 20.04


      Existe uma versão anterior deste tutorial, escrita por Justin Ellingwood.

      Introdução

      Ao armazenar dados críticos, ter um ponto único de falha é bastante arriscado. Embora muitos bancos de dados e outros softwares permitam que você distribua dados no contexto de um único aplicativo, outros sistemas podem operar no nível de sistema de arquivos para garantir que os dados sejam copiados para outro local sempre que eles são escritos para o disco.

      O GlusterFS é um sistema de arquivos de armazenamento conectado à rede que lhe permite agrupar recursos de armazenamento de várias máquinas. Desta forma, isso permite que você trate vários dispositivos de armazenamento que são distribuídos entre vários computadores como uma unidade única e mais poderosa. O GlusterFS também lhe dá a liberdade de criar diferentes tipos de configurações de armazenamento, muitas das quais são similares em funcionamento aos níveis RAID. Por exemplo, você pode distribuir os dados em diferentes nós no cluster, ou implementar redundância para uma melhor disponibilidade de dados.

      Objetivos

      Neste guia, você irá criar uma matriz de armazenamento em clusters redundante, também conhecida como um sistema de arquivos distribuído ou, como ela está referida na documentação do GlusterFS, uma Trusted Storage Pool (pool de armazenamento confiável). Isso irá proporcionar funcionalidades semelhantes a uma configuração RAID espelhada pela rede: cada servidor independente irá conter sua própria cópia dos dados, permitindo que suas aplicações acessem qualquer cópia, ajudando assim a distribuir sua carga de leitura.

      Esse cluster do GlusterFS redundante consistirá em dois servidores do Ubuntu 20.04. Isso irá agir de maneira semelhante a um servidor NAS com RAID espelhado. Então, você irá acessar o cluster a partir de um terceiro servidor Ubuntu 20.04 configurado para funcionar como um cliente do GlusterFS.

      Quando você adiciona dados a um volume do GlusterFS, esses dados são sincronizados para todas as máquinas na pool de armazenamento onde o volume está hospedado. Este tráfego entre nós não é criptografado por padrão, o que significa que há um risco dele ser interceptado por agentes maliciosos.

      Por isso, se você vai usar o GlusterFS na produção, é recomendado que você execute-o em uma rede isolada. Por exemplo, você pode configurá-lo para executar em uma *Virtual Private Cloud *(VPC) ou com um VPN em funcionamento entre cada um dos nós.

      Se você planeja implantar o GlusterFS na DigitalOcean, você pode configurá-lo em uma rede isolada adicionando sua infraestrutura de servidor a uma Virtual Private Network da Digital Ocean. Para obter detalhes sobre como configurar isso, consulte nossa documentação de produtos VPC.

      Pré-requisitos

      Para seguir este tutorial, você precisará de três servidores executando o Ubuntu 20.04. Cada servidor deve ter um usuário não-root com privilégios administrativos e um firewall configurado com o UFW. Para configurar isso, siga nosso guia de configuração inicial de servidor para o Ubuntu 20.04.

      Note: Como mencionado na seção de Objetivos, este tutorial irá guiá-lo para configurar dois dos seus servidores Ubuntu para que atuem como servidores em sua pool de armazenamento e o servidor restante para agir como um cliente que você usará para acessar esses nós.

      Para maior clareza, este tutorial irá se referir a essas máquinas com os seguintes nomes de host:

      Hostname Papel na pool de armazenamento
      gluster0 Servidor
      gluster1 Servidor
      gluster2 Cliente

      Os comandos que devem ser executados em gluster0 ou gluster1 terão fundo em azul e vermelho, respectivamente:

      Os comandos que só devem ser executados no cliente (gluster2) terão um fundo verde:

      Os comandos que podem ou devem ser executados em mais de uma máquina terão um fundo cinza:

      Passo 1 — Configurando a resolução de DNS em cada máquina

      Configurar algum tipo de resolução de nome de host entre cada computador pode ajudar na gestão da sua pool de armazenamento do Gluster. Desta forma, sempre que precisar fazer referência a uma de suas máquinas em um comando gluster mais tarde neste tutorial, faça isso com um nome de domínio de fácil memorização ou um apelido em vez dos respectivos endereços IP.

      Se você não tiver um nome de domínio sobrando ou se você quiser configurar algo rapidamente, você pode editar o arquivo /etc/hosts em cada computador como alternativa. Este é um arquivo especial em máquinas Linux, onde é possível configurar o sistema de forma estática para atribuir todos os nomes de host contidos no arquivo para endereços IP estáticos.

      Note: Se você quiser configurar seus servidores para se autenticarem com um domínio que você possua, será necessário primeiro obter um nome de domínio de registrador de domínios — como o Namecheap ou o Enom — e configurar os registros de DNS apropriados.

      Depois de configurar um registro A para cada servidor, você pode seguir em frente para o Passo 2. Conforme for seguindo este guia, certifique-se de substituir o glusterN.example.com e o glusterN pelo nome de domínio que direciona para o servidor respectivo referenciado no comando de exemplo.

      Se você obteve sua infraestrutura da DigitalOcean, é possível adicionar seu nome de domínio à DigitalOcean e, em seguida, configurar um registro A único para cada um de seus servidores.

      Usando seu editor de texto preferido, abra este arquivo com privilégios de root em cada uma das suas máquinas. Aqui, usaremos o nano:

      Por padrão, o arquivo vai ficar parecido com isto aqui,com os comentários removidos:

      /etc/hosts

      127.0.1.1 hostname hostname
      127.0.0.1 localhost
      
      ::1 ip6-localhost ip6-loopback
      fe00::0 ip6-localnet
      ff00::0 ip6-mcastprefix
      ff02::1 ip6-allnodes
      ff02::2 ip6-allrouters
      ff02::3 ip6-allhosts
      

      Em um dos seus servidores Ubuntu, adicione o endereço IP de cada servidor seguido dos nomes que você deseja utilizar para fazer referência a eles em comandos abaixo da definição local de host.

      No exemplo a seguir, cada servidor recebe um nome de host longo que segue o padrão de glusterN.example.com e um menor que segue o padrão de glusterN. Você pode alterar as partes glusterN.example.com e glusterN de cada linha para qualquer nome — ou nomes separados por espaços únicos — que você quiser usar para acessar cada servidor. Observe, porém, que este tutorial irá usar estes exemplos a todo momento:

      Nota: Se seus servidores fazem parte de uma pool de infraestrutura Virtual Private Cloud, você deve usar o endereço IP privado de cada servidor no arquivo /etc/hosts em vez de seus IP públicos.

      /etc/hosts

      . . .
      127.0.0.1       localhost
      first_ip_address gluster0.example.com gluster0
      second_ip_address gluster1.example.com gluster1
      third_ip_address gluster2.example.com gluster2
      
      . . .
      

      Quando você terminar de adicionar estas novas linhas ao arquivo /etc/hosts de uma máquina, copie e adicione-as aos arquivos /etc/hosts em suas outras máquinas. Cada arquivo /etc/hosts deve conter as mesmas linhas, ligando os endereços IP dos seus servidores aos nomes que você selecionou.

      Salve e feche cada arquivo quando você terminar. Se usou o nano, faça isso pressionando as teclas CTRL+X, Y e depois ENTER.

      Agora que você configurou a resolução de nomes de host entre cada um dos seus servidores, será mais fácil executar comandos mais tarde enquanto configura uma pool de armazenamento e um volume. Em seguida, você vai percorrer outro passo que deve ser concluído em cada um dos seus servidores. Isto é, você irá adicionar o arquivo de pacotes pessoais (PPA) oficial do projeto Gluster a cada um dos seus três servidores Ubuntu para garantir que você possa instalar a versão mais recente do GlusterFS.

      Passo 2 — Configurando as fontes de software em cada máquina

      Embora os repositórios APT padrão do Ubuntu 20.04 contém os pacotes do GlusterFS, no momento em que este tutorial está sendo escrito, eles não são as versões mais recentes. Uma maneira de instalar a última versão estável do GlusterFS (versão 7.6 no momento em que este tutorial está sendo escrito) é adicionando o PPA oficial do projeto Gluster a cada um dos seus três servidores Ubuntu.

      Adicione o PPA para os pacotes do GlusterFS executando o seguinte comando em cada servidor:

      • sudo add-apt-repository ppa:gluster/glusterfs-7

      Pressione ENTER quando solicitado para confirmar se você realmente deseja adicionar o PPA.

      Depois de adicionar o PPA, atualize o índice de pacotes local de cada servidor. Isso fará com que cada servidor reconheça os novos pacotes disponíveis:

      Depois de adicionar o PPA oficial do projeto Gluster a cada servidor e atualizar o índice de pacotes local, você está pronto para instalar os pacotes do GlusterFS necessários. No entanto, como duas de suas três máquinas irão atuar como servidores Gluster e a outra irá agir como cliente, há dois procedimentos de instalação e configuração separados. Primeiro, você irá instalar e configurar os componentes do servidor.

      Passo 3 — Instalando componentes do servidor e criando uma pool de armazenamento confiável

      Uma pool de armazenamento é qualquer quantidade de capacidade de armazenamento agregada a partir de mais de uma fonte de armazenamento. Neste passo, você irá configurar dois dos seus servidores — o gluster0 e o gluster1 — como os componentes do cluster.

      Em ambos o gluster0 e o gluster1, instale o pacote de servidor do GlusterFS digitando:

      • sudo apt install glusterfs-server

      Quando solicitado, pressione Y e então ENTER para confirmar a instalação.

      O processo de instalação configura automaticamente o GlusterFS para ser executado como um serviço do systemd. No entanto, ele não inicializa automaticamente o serviço ou o habilita para ser executado na inicialização do sistema.

      Para iniciar o glusterd, o serviço do GlusterFS, execute o seguinte comando systemctl start em ambos o gluster0 e gluster1:

      • sudo systemctl start glusterd.service

      Então, execute o seguinte comando em ambos os servidores. Isso permitirá que o serviço seja iniciado sempre que o servidor for inicializado:

      • sudo systemctl enable glusterd.service

      Depois disso, você pode verificar o status do serviço em ambos os servidores:

      • sudo systemctl status glusterd.service

      Se o serviço estiver em operação, você receberá um resultado parecido com este:

      Output

      ● glusterd.service - GlusterFS, a clustered file-system server Loaded: loaded (/lib/systemd/system/glusterd.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2020-06-02 21:32:21 UTC; 32s ago Docs: man:glusterd(8) Main PID: 14742 (glusterd) Tasks: 9 (limit: 2362) CGroup: /system.slice/glusterd.service └─14742 /usr/sbin/glusterd -p /var/run/glusterd.pid --log-level INFO

      Supondo que você tenha seguido o guia de configuração inicial do servidor pré-requisito, você terá configurado um firewall com o UFW em cada uma das suas máquinas. Por isso, é necessário abrir o firewall em cada nó antes de estabelecer comunicações entre eles e criar uma pool de armazenamento.

      O daemon do Gluster usa a porta 24007, então será necessário permitir que cada nó tenha acesso a essa porta através do firewall de cada um dos nós em sua pool de armazenamento. Para fazer isso, execute o seguinte comando no gluster0. Lembre-se de alterar gluster1_ip_address para o endereço IP do gluster1:

      • sudo ufw allow from gluster1_ip_address to any port 24007

      E execute o seguinte comando no gluster1. Novamente, certifique-se de alterar gluster0_ip_address para o endereço IP do gluster0:

      • sudo ufw allow from gluster0_ip_address to any port 24007

      Também será necessário permitir que sua máquina cliente (gluster2) tenha acesso a esta porta. Caso contrário, você encontrará problemas mais tarde quando for tentar montar o volume. Execute o seguinte comando tanto no gluster0 quanto no gluster1 para abrir esta porta para a sua máquina cliente:

      • sudo ufw allow from gluster2_ip_address to any port 24007

      Então, para garantir que nenhuma outra máquina seja capaz de acessar a porta do Gluster em ambos os servidores, adicione a seguinte regra ampla deny ao gluster0 e ao gluster1:

      Agora, você está pronto para estabelecer uma comunicação entre o gluster0 e o gluster1. Para fazer isso, você precisará executar o comando gluster peer probe em um dos seus nós. Não importa qual nó você use, mas o seguinte exemplo mostra o comando sendo executado no gluster0:

      • sudo gluster peer probe gluster1

      Essencialmente, este comando diz ao gluster0 para confiar no gluster1 e registrá-lo como parte de sua pool de armazenamento. Se a investigação for bem-sucedida, ela irá retornar o seguinte resultado:

      Output

      peer probe: success

      Você pode verificar se os nós estão se comunicando a qualquer momento, executando o comando gluster peer status em cada um dos dois. Neste exemplo, ele está sendo executado no gluster1:

      Se você executar este comando do gluster1, ele irá mostrar um resultado desta forma:

      Output

      Number of Peers: 1 Hostname: gluster0.example.com Uuid: a3fae496-c4eb-4b20-9ed2-7840230407be State: Peer in Cluster (Connected)

      Neste momento, seus dois servidores estão se comunicando e prontos para criar volumes de armazenamento um com o outro.

      Passo 4 — Criando um volume de armazenamento

      Lembre-se que o objetivo principal deste tutorial é criar uma pool de armazenamento redundante. Para este fim, você irá configurar um volume com funcionalidade de réplica. Ele permitirá que você mantenha várias cópias dos seus dados e impedirá que seu cluster tenha um ponto único de falha.

      Para criar um volume, você irá usar o comando gluster volume create com esta sintaxe geral:

      sudo gluster volume create volume_name replica number_of_servers domain1.com:/path/to/data/directory domain2.com:/path/to/data/directory force
      

      Veja o que os argumentos e opções do comando gluster volume create significam:

      • volume_name: Este é o nome que você irá usar para se referir ao volume depois de ele ser criado. O comando de exemplo a seguir cria um volume chamado volume1.
      • replica number_of_servers: Após o nome do volume, você pode definir que tipo de volume você deseja criar. Lembre-se que o objetivo deste tutorial é criar uma pool de armazenamento redundante, então vamos usar o tipo de volume replica. Isso requer um argumento que indique para quantos servidores os dados do volume serão replicados (2, no caso deste tutorial).
      • domain1.com:/… e domain2.com:/…: Eles definem a localização das máquinas e do diretório do bricks — o termo do GlusterFS para sua unidade básica de armazenamento, que inclui todos os diretórios em todas as máquinas que sirvam como parte ou uma cópia de um volume maior — que formarão o volume1. O exemplo a seguir irá criar um diretório chamado gluster-storage no diretório root de ambos os servidores.
      • force: Essa opção irá sobrescrever quaisquer avisos ou opções que de outra forma apareceriam e interromperiam a criação do volume.

      Seguindo as convenções estabelecidas anteriormente neste tutorial, você pode executar este comando para criar um volume. Observe que pode executá-lo tanto a partir do gluster0 quanto do gluster1:

      • sudo gluster volume create volume1 replica 2 gluster0.example.com:/gluster-storage gluster1.example.com:/gluster-storage force

      Se o volume for criado com sucesso, você receberá o seguinte resultado:

      Output

      volume create: volume1: success: please start the volume to access data

      Neste momento, seu volume foi criado, mas ele ainda não está ativo. Você pode iniciar o volume e torná-lo disponível para uso executando o seguinte comando novamente a partir de um dos seus servidores do Gluster:

      • sudo gluster volume start volume1

      Você receberá este resultado se o volume for iniciado corretamente:

      Output

      volume start: volume1: success

      Em seguida, verifique se o volume está online. Execute o seguinte comando a partir de um dos seus nós:

      • sudo gluster volume status

      Isso irá retornar um resultado semelhante a este:

      Output

      Status of volume: volume1 Gluster process TCP Port RDMA Port Online Pid ------------------------------------------------------------------------------ Brick gluster0.example.com:/gluster-storage 49152 0 Y 18801 Brick gluster1.example.com:/gluster-storage 49152 0 Y 19028 Self-heal Daemon on localhost N/A N/A Y 19049 Self-heal Daemon on gluster0.example.com N/A N/A Y 18822 Task Status of Volume volume1 ------------------------------------------------------------------------------ There are no active volume tasks

      Com base neste resultado, os bricks em ambos os servidores estão online.

      Como um passo final para configurar seu volume, você precisará abrir o firewall em ambos os servidores para que sua máquina cliente seja capaz de se conectar e montar o volume. De acordo com o resultado amostral do comando anterior, o volume1 está em execução na porta 49152 em ambas as máquinas. Esta é a porta padrão do GlusterFS para seu volume inicial, e o próximo volume que você criar irá usar a porta 49153, então 49154 e assim por diante.

      Execute o seguinte comando em ambos o gluster0 e o gluster1 para permitir que o gluster2 tenha acesso a esta porta através dos seus respectivos firewalls:

      • sudo ufw allow from gluster2_ip_address to any port 49152

      Então, para uma camada adicional de segurança, adicione outra regra ampla deny para a porta do volume tanto no gluster0 quanto no gluster1. Isso irá garantir que nenhuma máquina que não seja o seu cliente possa acessar o volume em ambos os servidores:

      Agora que seu volume está em operação, você pode configurar sua máquina cliente e começar a usá-la remotamente.

      Passo 5 — Instalando e configurando componentes do cliente

      Seu volume agora está configurado e disponível para uso pela sua máquina cliente. Apesar disso, antes de começar, você precisa instalar o pacote glusterfs-client a partir do PPA que você configurou no Passo 1 na sua máquina cliente. As dependências deste pacote incluem algumas das bibliotecas comuns e módulos de tradutor do GlusterFS, além das ferramentas FUSE necessárias para que ele funcione.

      Execute o seguinte comando no gluster2:

      • sudo apt install glusterfs-client

      Você irá montar seu volume de armazenamento remoto em seu computador cliente em breve. Antes que possa fazer isso, no entanto, você precisa criar um ponto de montagem. Tradicionalmente, ele está localizado no diretório /mnt, mas qualquer lugar que seja conveniente pode ser usado.

      Para simplificar, crie um diretório chamado /storage-pool em sua máquina cliente para servir como o ponto de montagem. Este nome de diretório começa com uma barra (/) que o coloca no diretório root. Sendo assim, você precisará criá-lo com privilégios sudo:

      Agora, você pode montar o volume remoto. Antes disso, porém, dê uma olhada na sintaxe do comando mount que você irá usar para isso.

      sudo mount -t glusterfs domain1.com:volume_name /path/to/mount/point
      

      O mount é um utilitário encontrado em muitos sistemas operacionais semelhantes ao Unix. Ele é usado para montar sistemas de arquivos — qualquer coisa desde dispositivos de armazenamento externo, como cartões SD ou pendrives, até armazenamento ligado à rede como no caso deste tutorial — em diretórios no sistema de arquivos existente da máquina. A sintaxe do comando mount que você irá usar inclui a opção -t, que requer três argumentos: o tipo do sistema de arquivos a ser montado, o dispositivo onde o sistema de arquivos a ser montado pode ser encontrado, e o diretório no cliente onde você irá montar o volume.

      Observe que neste exemplo de sintaxe, o argumento do dispositivo aponta para um nome de host seguido por dois pontos e depois o nome do volume. O GlusterFS abstrai os diretórios de armazenamento reais em cada host, o que significa que este comando não procura montar o diretório /gluster-storage, mas sim o volume volume1.

      Também observe que você só precisa especificar um membro do cluster de armazenamento. Isso pode ser qualquer um dos nós, pois o serviço do GlusterFS os trata como uma máquina.

      Execute o seguinte comando em sua máquina cliente (gluster2) para montar o volume no diretório /storage-pool que você criou:

      • sudo mount -t glusterfs gluster0.example.com:/volume1 /storage-pool

      Depois disso, execute o comando df. Isso irá exibir a quantidade de espaço em disco disponível para sistemas de arquivos aos quais o usuário que o invocou tem acesso:

      Este comando irá mostrar que o volume do GlusterFS está montado na localização correta:

      Output

      Filesystem 1K-blocks Used Available Use% Mounted on . . . gluster0.example.com:/volume1 50633164 1938032 48695132 4% /storage-pool

      Agora, teste se todos os dados que você escreve no volume no seu cliente são replicados para os nós do servidor como esperado.

      Passo 6 — Testando recursos de redundância

      Agora que você configurou seu cliente para usar sua pool de armazenamento e volume, você pode testar sua funcionalidade.

      Em sua máquina cliente (gluster2), navegue até o ponto de montagem que você definiu no passo anterior:

      Em seguida, crie alguns arquivos de teste. O comando a seguir cria dez arquivos vazios separados em sua pool de armazenamento:

      • sudo touch file_{0..9}.test

      Se você examinar os diretórios de armazenamento definidos anteriormente em cada host de armazenamento, você irá descobrir que todos os arquivos estão presentes em cada sistema.

      No gluster0:

      Output

      file_0.test file_2.test file_4.test file_6.test file_8.test file_1.test file_3.test file_5.test file_7.test file_9.test

      Da mesma forma, no gluster1:

      Output

      file_0.test file_2.test file_4.test file_6.test file_8.test file_1.test file_3.test file_5.test file_7.test file_9.test

      Como estes resultados mostram, os arquivos de teste que você adicionou ao cliente também foram escritos em ambos os seus nós.

      Se um dos nós em seu cluster de armazenamento estiver desligado em algum momento, eles podem perder a sincronia com o pool de armazenamento, caso haja alterações feitas no sistema de arquivos. Fazer uma operação de leitura no ponto de montagem do cliente depois que o nó voltar a ficar online irá alertar o nó para obter qualquer arquivo em falta:

      Agora que verificou que seu volume de armazenamento está montado corretamente e pode replicar dados para ambas as máquinas no cluster, você pode bloquear o acesso à pool de armazenamento.

      Passo 7 — Restringindo recursos de redundância

      Neste momento, qualquer computador pode se conectar ao seu volume de armazenamento sem nenhuma restrição. Você pode mudar isso alterando a opção auth.allow que define os endereços IP de quais clientes têm acesso ao volume.

      Se estiver usando a configuração do /etc/hosts, os nomes que você configurou para cada servidor não serão encaminhados corretamente. Você deve usar um endereço IP estático disso.ao invés disso. Por outro lado, se você estiver usando registros DNS, o nome de domínio que você configurou irá funcionar aqui.

      Em um dos seus nós de armazenamento (gluster0 ou gluster1), execute o seguinte comando:

      • sudo gluster volume set volume1 auth.allow gluster2_ip_address

      Se o comando terminar com sucesso, ele irá retornar este resultado:

      Output

      volume set: success

      Se precisar remover a restrição a qualquer momento, você pode digitar:

      • sudo gluster volume set volume1 auth.allow *

      Isso permitirá as conexões de qualquer máquina novamente. Isso é inseguro, mas pode ser útil para depurar problemas.

      Se você tiver vários clientes, pode especificar os endereços IP ou nomes de domínio deles ao mesmo tempo (dependendo se estiver usando a resolução /etc/hosts ou a resolução de nomes de host DNS), separados por vírgulas:

      • sudo gluster volume set volume1 auth.allow gluster_client1_ip,gluster_client2_ip

      Seu pool de armazenamento agora está configurado, seguro e pronto para uso. Em seguida, você irá aprender alguns comandos que lhe ajudarão a obter informações sobre o status da sua pool de armazenamento.

      Quando começar a alterar algumas das configurações para seu armazenamento do GlusterFS, você pode se confundir com as opções disponíveis, quais volumes estão ativos e quais nós estão associados a cada volume.

      Há vários comandos diferentes que estão disponíveis em seus nós para recuperar esses dados e interagir com sua pool de armazenamento.

      Se você quiser informações sobre cada um dos seus volumes, execute o comando gluster volume info:

      Output

      Volume Name: volume1 Type: Replicate Volume ID: a1e03075-a223-43ab-a0f6-612585940b0c Status: Started Snapshot Count: 0 Number of Bricks: 1 x 2 = 2 Transport-type: tcp Bricks: Brick1: gluster0.example.com:/gluster-storage Brick2: gluster1.example.com:/gluster-storage Options Reconfigured: auth.allow: gluster2_ip_address transport.address-family: inet storage.fips-mode-rchecksum: on nfs.disable: on performance.client-io-threads: off

      Da mesma forma, para obter informações sobre quaisquer pares aos quais este nó esteja conectado, você pode digitar:

      Number of Peers: 1
      
      Hostname: gluster0.example.com
      Uuid: cb00a2fc-2384-41ac-b2a8-e7a1793bb5a9
      State: Peer in Cluster (Connected)
      

      Se quiser informações detalhadas sobre como cada nó está desempenhando, faça um perfil de volume digitando:

      • sudo gluster volume profile volume_name start

      Quando este comando for concluído, obtenha as informações que foram reunidas digitando:

      • sudo gluster volume profile volume_name info

      Output

      Brick: gluster0.example.com:/gluster-storage -------------------------------------------- Cumulative Stats: %-latency Avg-latency Min-Latency Max-Latency No. of calls Fop --------- ----------- ----------- ----------- ------------ ---- 0.00 0.00 us 0.00 us 0.00 us 30 FORGET 0.00 0.00 us 0.00 us 0.00 us 36 RELEASE 0.00 0.00 us 0.00 us 0.00 us 38 RELEASEDIR Duration: 5445 seconds Data Read: 0 bytes Data Written: 0 bytes Interval 0 Stats: %-latency Avg-latency Min-Latency Max-Latency No. of calls Fop --------- ----------- ----------- ----------- ------------ ---- 0.00 0.00 us 0.00 us 0.00 us 30 FORGET 0.00 0.00 us 0.00 us 0.00 us 36 RELEASE 0.00 0.00 us 0.00 us 0.00 us 38 RELEASEDIR Duration: 5445 seconds Data Read: 0 bytes Data Written: 0 bytes . . .

      Como mostrado anteriormente, para uma lista de todos os componentes associados ao GlusterFS em execução em cada um dos seus nós, execute o comando gluster volume status:

      • sudo gluster volume status

      Output

      Status of volume: volume1 Gluster process TCP Port RDMA Port Online Pid ------------------------------------------------------------------------------ Brick gluster0.example.com:/gluster-storage 49152 0 Y 19003 Brick gluster1.example.com:/gluster-storage 49152 0 Y 19040 Self-heal Daemon on localhost N/A N/A Y 19061 Self-heal Daemon on gluster0.example.com N/A N/A Y 19836 Task Status of Volume volume1 ------------------------------------------------------------------------------ There are no active volume tasks

      Se você estiver administrando seus volumes de armazenamento do GlusterFS, pode ser uma boa ideia adentrar-se no console do GlusterFS. Isso permitirá que você interaja com seu ambiente do GlusterFS sem precisar digitar sudo gluster antes de tudo:

      Isso lhe dará um prompt onde você pode digitar seus comandos. O help é um bom recurso para se orientar:

      Output

      peer help - display help for peer commands volume help - display help for volume commands volume bitrot help - display help for volume bitrot commands volume quota help - display help for volume quota commands snapshot help - display help for snapshot commands global help - list global commands

      Quando você terminar, execute exit para sair do console do Gluster:

      Com isso, você está pronto para começar a integrar o GlusterFS com seu próximo aplicativo.

      Conclusão

      Após completar este tutorial, você tem agora um sistema de armazenamento redundante que lhe permitirá escrever em dois servidores separados simultaneamente. Isso pode ser útil para uma série de aplicativos e pode garantir que seus dados estejam disponíveis mesmo quando um servidor cair.



      Source link

      Cómo acceder remotamente a aplicaciones GUI usando Docker y Caddy en Ubuntu 18.04


      El autor seleccionó la Free and Open Source Fund para recibir una donación como parte del programa Write for DOnations.

      Introducción

      Aún con la creciente popularidad de los servicios en la nube, la necesidad de ejecutar aplicaciones nativas sigue existiendo.

      Con noVNC y TigerVNC, puede ejecutar aplicaciones nativas dentro de un contenedor Docker y acceder a ellas remotamente usando un navegador web. Adicionalmente, puede ejecutar su aplicación en un servidor con más recursos del sistema de los que pueda tener disponibles localmente, lo que puede proporcionar mayor flexibilidad cuando se ejecutan grandes aplicaciones.

      En este tutorial, pondrá en un contendor Mozilla Thunderbird, un cliente de correo electrónico, usando Docker. Tras ello, lo protegerá y proporcionará acceso remoto usando el servidor web Caddy.

      Cuando haya terminado, podrá acceder a Thunderbird desde cualquier dispositivo usando únicamente un navegador web. Opcionalmente, podrá acceder localmente a los archivos usando WebDAV. También tendrá una imagen Docker completamente autocontenida que puede ejecutar en cualquier lugar.

      Requisitos previos

      Antes de iniciar esta guía, necesitará lo siguiente:

      Paso 1: Crear la configuración supervisord

      Ahora que su servidor está ejecutándose y Docker está instalado, está listo para comenzar a configurar el contenedor de su aplicación. Ya que su contenedor consta de varios componentes, deberá usar un administrador de procesos para iniciarlos y monitorizarlos. Aquí usará supervisord. supervisord es un gestor de procesos escrito en Python que se utiliza a menudo para organizar contenedores complejos.

      Primero, cree y entre en un directorio llamado thunderbird para su contenedor.

      • mkdir ~/thunderbird
      • cd ~/thunderbird

      Ahora cree y abra un archivo llamado supervisord.conf usando nano o su editor preferido:

      Ahora añada este primer bloque de código en supervisord.conf, lo que definirá las opciones globales para supervisord:

      ~/thunderbird/supervisord.conf

      [supervisord]
      nodaemon=true
      pidfile=/tmp/supervisord.pid
      logfile=/dev/fd/1
      logfile_maxbytes=0
      

      En este bloque, está configurando supervisord. Deberá establecer nodaemon a true porque se ejecutará dentro de un contenedor Docker como el punto de entrada. Por tanto, querrá que permanezca en ejecución en primer plano. También configura pidfile a una ruta accesible por un usuario non-root (más sobre esto más tarde), y logfile to stdout para que pueda ver los registros.

      A continuación, añada otro bloque de código pequeño a supervisord.conf. Este bloque inicia TigerVNC que es un servidor VNC/X11 combinado:

      ~/thunderbird/supervisord.conf

      ...
      [program:x11]
      priority=0
      command=/usr/bin/Xtigervnc -desktop "Thunderbird" -localhost -rfbport 5900 -SecurityTypes None -AlwaysShared -AcceptKeyEvents -AcceptPointerEvents -AcceptSetDesktopSize -SendCutText -AcceptCutText :0
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      En este bloque, está configurando el servidor X11. X11 es un protocolo de servidor de visualización, que es lo que permite que se ejecuten las aplicaciones GUI. Tenga en cuenta que en el futuro se sustituirá con Wayland, pero el acceso remoto aún está en desarrollo.

      Para este contenedor, está usando TigerVNC y está integrado en el servidor VNC. Esto tiene varias ventajas sobre el uso de un servidor X11 y VNC:

      • Tiempo de respuesta más rápido, ya que el dibujo de la GUI se realiza directamente en el servidor VNC en vez de hacerse en un framebuffer intermedio (la memoria que almacena los contenidos de la pantalla).
      • Cambio de tamaño automático de la pantalla, que permite a la aplicación remota cambiar de tamaño automáticamente para que se ajuste al cliente (en este caso, la ventana de su navegador web).

      Si lo desea, puede cambiar el argumento para la opción -desktop desde Thunderbird a otra cosa que elija. El servidor mostrará su opción como el título de la página web usada para acceder a su aplicación.

      Ahora, vamos a añadir un tercer bloque de código a supervisord.conf para iniciar easy-novnc:

      ~/thunderbird/supervisord.conf

      ...
      [program:easy-novnc]
      priority=0
      command=/usr/local/bin/easy-novnc --addr :8080 --host localhost --port 5900 --no-url-password --novnc-params "resize=remote"
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      En este bloque, está configurando easy-novnc, un servidor independiente que ofrece un envoltorio alrededor de noVNC. Este servidor realiza dos funciones. Primero, proporciona una página sencilla de conexión que le permite configurar opciones para la conexión, y le permite establecer las predeterminadas. Segundo, realiza proxy a VNC sobre WebSocket, lo que permite el acceso a través de un navegador web ordinario.

      Normalmente, el cambio de tamaño se realiza en el lado del cliente (es decir, escala de imagen), pero está usando la opción resize=remote para aprovechar los ajustes de resolución remota de TigerVNC. Esto también proporciona una menor latencia en dispositivos más lentos, como Chromebooks de gama baja:

      Nota: Este tutorial utiliza easy-novnc. Si lo desea, puede usar websockfy y un servidor web independiente. La ventaja de easy-novnc es que el uso de memoria y el tiempo de inicio es significativamente menor que si fuese auto-contenido. easy-novnc también proporciona una página conexión más limpia que la de noVNC predeterminado, y permite establecer opciones predeterminadas que son útiles para esta configuración (como resize=remote).

      Ahora añada el siguiente bloque a su configuración para iniciar OpenBox, el gestor de ventanas:

      ~/thunderbird/supervisord.conf

      ...
      [program:openbox]
      priority=1
      command=/usr/bin/openbox
      environment=DISPLAY=:0
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      En este bloque, está configurando OpenBox, un gestor de ventanas X11 ligero. Podría omitir este paso, pero sin él no tendría las barras de título o podría cambiar el tamaño de las ventanas.

      Finalmente, vamos a añadir el último bloque a supervisord.conf, que iniciará la aplicación principal:

      ~/thunderbird/supervisord.conf

      ...
      [program:app]
      priority=1
      environment=DISPLAY=:0
      command=/usr/bin/thunderbird
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      En este bloque final, está configurando priority a 1 para garantizar que Thunderbird se inicia tras TigerVNC, o encontrará una condición de carrera o fallaría aleatoriamente al inicio. También configuramos autorestart=true para que vuelva a abrir automáticamente la aplicación si se cierra por error. La variable de entorno DISPLAY indica a la aplicación que se muestre en el servidor VNC que configuró anteriormente.

      Este es el aspecto que tendrá su supervisord.conf completado:

      ~/thunderbird/supervisord.conf

      [supervisord]
      nodaemon=true
      pidfile=/tmp/supervisord.pid
      logfile=/dev/fd/1
      logfile_maxbytes=0
      
      [program:x11]
      priority=0
      command=/usr/bin/Xtigervnc -desktop "Thunderbird" -localhost -rfbport 5900 -SecurityTypes None -AlwaysShared -AcceptKeyEvents -AcceptPointerEvents -AcceptSetDesktopSize -SendCutText -AcceptCutText :0
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      
      [program:easy-novnc]
      priority=0
      command=/usr/local/bin/easy-novnc --addr :8080 --host localhost --port 5900 --no-url-password --novnc-params "resize=remote"
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      
      [program:openbox]
      priority=1
      command=/usr/bin/openbox
      environment=DISPLAY=:0
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      
      [program:app]
      priority=1
      environment=DISPLAY=:0
      command=/usr/bin/thunderbird
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      Si desea poner una aplicación diferente en contenedor, sustituya /usr/bin/thunderbird con la ruta al ejecutable de su aplicación. De lo contrario, estará listo para configurar el menú principal de su GUI.

      Paso 2: Configurar el menú de OpenBox

      Ahora que su gestor de procesos está configurado, vamos a configurar el menú de OpenBox. Este menú nos permite abrir aplicaciones dentro del contenedor. También incluiremos un monitor de terminal y procesos para depurar si es necesario.

      Dentro del directorio de la aplicación, utilice nano o su editor de texto favorito para crear y abrir un nuevo archivo llamado menu.xml:

      • nano ~/thunderbird/menu.xml

      Ahora añada el siguiente código a menu.xml:

      ~/thunderbird/menu.xml

      <?xml version="1.0" encoding="utf-8"?>
      <openbox_menu xmlns="http://openbox.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://openbox.org/ file:///usr/share/openbox/menu.xsd">
          <menu id="root-menu" label="Openbox 3">
              <item label="Thunderbird">
                  <action name="Execute">
                      <execute>/usr/bin/thunderbird</execute>
                  </action>
              </item>
              <item label="Terminal">
                  <action name="Execute">
                      <execute>/usr/bin/x-terminal-emulator</execute>
                  </action>
              </item>
              <item label="Htop">
                  <action name="Execute">
                      <execute>/usr/bin/x-terminal-emulator -e htop</execute>
                  </action>
              </item>
          </menu>
      </openbox_menu>
      

      Este archivo XML contiene los elementos del menú que aparecerán cuando haga clic con el botón derecho sobre el escritorio. Cada elemento consta de una etiqueta y una acción.

      Si desea añadir al contenedor una aplicación diferente, sustituya /usr/bin/thunderbird con la ruta al ejecutable de su aplicación y cambie la etiqueta del elemento.

      Paso 3: Crear el Dockerfile

      Ahora que OpenBox está configurado, creará el Dockerfile, que une todo.

      Crear un Dockerfile en el directorio de su contenedor:

      • nano ~/thunderbird/Dockerfile

      Para comenzar, vamos a añadir algún código para crear easy-novnc:

      ~/thunderbird/Dockerfile

      FROM golang:1.14-buster AS easy-novnc-build
      WORKDIR /src
      RUN go mod init build && 
          go get github.com/geek1011/easy-novnc@v1.1.0 && 
          go build -o /bin/easy-novnc github.com/geek1011/easy-novnc
      

      En la primera etapa, está creando easy-novnc. Esto se hace en una etapa independiente para mayor simplificada y para ahorrar espacio; no necesita toda la cadena de herramientas de go en su imagen final. Observe @v1.1.0 en el comando de compilación. Esto garantiza que el resultado sea determinista, lo cual es importante porque Docker captura el resultado de cada paso. Si no hubiese especificado una versión explícita, Docker haría referencia a la versión más reciente de easy-novnc en el momento en que se compiló la imagen por primera vez. Además, desea garantizar que descarga una versión específica de easy-novnc, en el caso de que se realicen cambios de ruptura en la interfaz CLI.“”“”

      Ahora vamos a crear la segunda etapa que será la imagen final. Aquí usará Debian 10 (buster) como imagen base. Observe que dado que se está ejecutando en un contenedor, funcionará independientemente de la distribución que esté ejecutando en su servidor.

      A continuación, añada el siguiente bloque a su Dockerfile:

      ~/thunderbird/Dockerfile

      ...
      FROM debian:buster
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends openbox tigervnc-standalone-server supervisor gosu && 
          rm -rf /var/lib/apt/lists && 
          mkdir -p /usr/share/desktop-directories
      

      En esta instrucción, está instalando Debian 10 como su imagen base y luego instalando el mínimo necesario para ejecutar aplicaciones GUI en su contenedor. Observe que ejecuta apt-get update como parte de la misma instrucción para evitar problemas de captura desde Docker. Para ahorrar espacio, también está eliminando las listas de paquetes descargadas posteriormente (los paquetes en caché en sí mismos se eliminan por defecto). Está creando /usr/share/desktop-directories porque algunas aplicaciones dependen de que exista el directorio.

      Vamos a añadir otro bloque de código pequeño:

      ~/thunderbird/Dockerfile

      ...
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends lxterminal nano wget openssh-client rsync ca-certificates xdg-utils htop tar xzip gzip bzip2 zip unzip && 
          rm -rf /var/lib/apt/lists
      

      En esta instrucción, está instalando algunas utilidades y paquetes útiles de uso general. Son interesantes xdg-utils (que proporciona los comandos base usados por las aplicaciones de escritorio en Linux) y ca-certificates (que instala los certificados raíz para permitirnos acceder a los sitios HTTPS).

      Ahora, podemos añadir las instrucciones para la aplicación principal:

      ~/thunderbird/Dockerfile

      ...
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends thunderbird && 
          rm -rf /var/lib/apt/lists
      

      Como antes, aquí estamos instalando la aplicación. Si añade una aplicación diferente al contenedor, puede sustituir estos comandos con los necesarios para instalar su aplicación específica. Algunas aplicaciones requerirán un poco más de trabajo para ejecutarse dentro de Docker. Por ejemplo, si está instalando una aplicación que utiliza Chrome, Chromium o QtWebEngine, deberá usar el argumento de línea de comando --no-sandbox porque no será compatible en Docker.

      A continuación, vamos a comenzar añadiendo las instrucciones para añadir las últimas líneas al contenedor:

      ~/thunderbird/Dockerfile

      ...
      COPY --from=easy-novnc-build /bin/easy-novnc /usr/local/bin/
      COPY menu.xml /etc/xdg/openbox/
      COPY supervisord.conf /etc/
      EXPOSE 8080
      

      Aquí está añadiendo los archivos de configuración que creó anteriormente a la imagen y copiando el binario easy-novnc de la primera etapa.

      Este siguiente bloque de código crea el directorio de datos y añade un usuario dedicado para su aplicación. Esto es importante porque algunas aplicaciones no se ejecutan como root. También es una buena práctica no ejecutar aplicaciones como root, incluso en un contenedor.

      ~/thunderbird/Dockerfile

      ...
      RUN groupadd --gid 1000 app && 
          useradd --home-dir /data --shell /bin/bash --uid 1000 --gid 1000 app && 
          mkdir -p /data
      VOLUME /data
      

      Para garantizar un UID/GID consistente para los archivos, está estableciendo explícitamente ambos a 1000. También está montando un volumen sobre el directorio de datos para garantizar que persiste entre los reinicios.

      Finalmente, vamos a añadir las instrucciones para iniciar todo:

      ~/thunderbird/Dockerfile

      ...
      CMD ["sh", "-c", "chown app:app /data /dev/stdout && exec gosu app supervisord"]
      

      Al establecer el comando predeterminado a supervisord, el administrador iniciará los procesos requeridos para ejecutar su aplicación. En este caso, está usando CMD en vez de ENTRYPOINT. En la mayoría de los casos, no supondría una diferencia, pero usar CMD es mejor para este fin por algunos motivos. Primero, supervisord no toma ningún argumento que sería relevante para nosotros, y si proporciona argumentos al contenedor, sustituye CMD y se anexan a ENTRYPOINT. Segundo, usar CMD nos permite proporcionar un comando completamente diferente (que se será ejecutado por /bin/sh -c) cuando se pasan argumentos al contenedor, lo que hace que la depuración sea más fácil.

      Y finalmente, deberá ejecutar chown como raíz antes de iniciar supervisord para evitar problemas de permisos sobre el volumen de datos y para permitir que se abran los procesos secundarios stdout. Esto también significa que deberá usar gosu en vez de la instrucción USER para cambiar al usuario.

      Este es el aspecto que tendrá su archivo Dockerfile completado:

      ~/thunderbird/Dockerfile

      FROM golang:1.14-buster AS easy-novnc-build
      WORKDIR /src
      RUN go mod init build && 
          go get github.com/geek1011/easy-novnc@v1.1.0 && 
          go build -o /bin/easy-novnc github.com/geek1011/easy-novnc
      
      FROM debian:buster
      
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends openbox tigervnc-standalone-server supervisor gosu && 
          rm -rf /var/lib/apt/lists && 
          mkdir -p /usr/share/desktop-directories
      
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends lxterminal nano wget openssh-client rsync ca-certificates xdg-utils htop tar xzip gzip bzip2 zip unzip && 
          rm -rf /var/lib/apt/lists
      
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends thunderbird && 
          rm -rf /var/lib/apt/lists
      
      COPY --from=easy-novnc-build /bin/easy-novnc /usr/local/bin/
      COPY menu.xml /etc/xdg/openbox/
      COPY supervisord.conf /etc/
      EXPOSE 8080
      
      RUN groupadd --gid 1000 app && 
          useradd --home-dir /data --shell /bin/bash --uid 1000 --gid 1000 app && 
          mkdir -p /data
      VOLUME /data
      
      CMD ["sh", "-c", "chown app:app /data /dev/stdout && exec gosu app supervisord"]
      

      Guarde y cierre su Dockerfile. Ahora estamos listos para crear y ejecutar nuestro contenedor, y luego acceder a Thunderbird – una aplicación GUI.

      Paso 4: Crear y ejecutar el contenedor

      El siguiente paso es crear su contenedor y configurarlo para que se ejecute al inicio. También configurará un volumen para conservar los datos de la aplicación entre reinicios y actualizaciones.

      Primero, cree su contenedor. Asegúrese de ejecutar estos comandos en el directorio ~/thunderbird:

      • docker build -t thunderbird .

      Ahora cree una nueva red que será compartida entre los contenedores de la aplicación:

      • docker network create thunderbird-net

      A continuación, cree un volumen para almacenar los datos de la aplicación:

      • docker volume create thunderbird-data

      Finalmente, ejecútelo para que se reinicie automáticamente:

      • docker run --detach --restart=always --volume=thunderbird-data:/data --net=thunderbird-net --name=thunderbird-app thunderbird

      Tenga en cuenta que si lo desea, puede sustituir thunderbird-app tras la opción --nombre con un nombre diferente. Sea cual sea su elección, su aplicación ahora está en contenedor y ejecutándose. Ahora vamos a usar el servidor web Caddy para protegerla y conectar remotamente a ella.

      Paso 5: Configurar Caddy

      En este paso, configurará el servidor web Caddy para proporcionar autenticación y, opcionalmente, acceso remoto a los archivos sobre WebDAV. Para mayor simplicidad, y para permitirle usarlo con su proxy inverso existente, lo ejecutará en otro contenedor.

      Cree un nuevo directorio y muévalo dentro:

      Ahora cree un nuevo Dockerfile usando nano o su editor preferido:

      Luego, añada las siguientes directivas:

      ~/caddy/Dockerfile

      FROM golang:1.14-buster AS caddy-build
      WORKDIR /src
      RUN echo 'module caddy' > go.mod && 
          echo 'require github.com/caddyserver/caddy/v2 v2.0.0' >> go.mod && 
          echo 'require github.com/mholt/caddy-webdav v0.0.0-20200523051447-bc5d19941ac3' >> go.mod
      RUN echo 'package main' > caddy.go && 
          echo 'import caddycmd "github.com/caddyserver/caddy/v2/cmd"' >> caddy.go && 
          echo 'import _ "github.com/caddyserver/caddy/v2/modules/standard"' >> caddy.go && 
          echo 'import _ "github.com/mholt/caddy-webdav"' >> caddy.go && 
          echo 'func main() { caddycmd.Main() }' >> caddy.go
      RUN go build -o /bin/caddy .
      
      FROM debian:buster
      
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends gosu && 
          rm -rf /var/lib/apt/lists
      
      COPY --from=caddy-build /bin/caddy /usr/local/bin/
      COPY Caddyfile /etc/
      EXPOSE 8080
      
      RUN groupadd --gid 1000 app && 
          useradd --home-dir /data --shell /bin/bash --uid 1000 --gid 1000 app && 
          mkdir -p /data
      VOLUME /data
      
      WORKDIR /data
      CMD ["sh", "-c", "chown app:app /data && exec gosu app /usr/local/bin/caddy run -adapter caddyfile -config /etc/Caddyfile"]
      

      Este Dockerfile crea Caddy con el complemento WebDAV habilitado, y luego lo abre en el puerto 8080 con Caddyfile en /etc/Caddyfile. Guarde y cierre el archivo.

      A continuación, configurará el servidor web Caddy. Cree un archivo llamado Caddyfile en el directorio que acaba de crear:

      Ahora añada el siguiente bloque de código a su Caddyfile:

      ~/caddy/Caddyfile

      {
          order webdav last
      }
      :8080 {
          log
          root * /data
          reverse_proxy thunderbird-app:8080
      
          handle /files/* {
              uri strip_prefix /files
              file_server browse
          }
          redir /files /files/
      
          handle /webdav/* {
              uri strip_prefix /webdav
              webdav
          }
          redir /webdav /webdav/
      
          basicauth /* {
              {env.APP_USERNAME} {env.APP_PASSWORD_HASH}
          }
      }
      

      Este Caddyfile realiza proxy el directorio raíz al contenedor thunderbird-app que creó en el Paso 4 (Docker lo resuelve a la IP correcta). También servirá como un navegador de archivo basado en web solo lectura en /files y para ejecutar el servidor WebDAV en /webdav que puede montar localmente para acceder a sus archivos. El nombre de usuario y la contraseña se leen desde las variables de entorno APP_USERNAME y APP_PASSWORD_HASH.

      Ahora cree el contenedor:

      • docker build -t thunderbird-caddy .

      Caddy v.2 requiere que haga hash a su contraseña deseada. Ejecute el siguiente comando y recuerde sustituir mypass con una contraseña fuerte que elija:

      • docker run --rm -it thunderbird-caddy caddy hash-password -plaintext 'mypass'

      Este comando dará como resultado una cadena de caracteres. Copie esto a su portapapeles para prepararse para ejecutar el siguiente comando.

      Ahora está listo para ejecutar el contenedor. Asegúrese de sustituir myuser con un nombre de usuario que elija, y sustituya mypass-hash con el resultado del comando que ejecutó en el paso anterior. Puede cambiar también el puerto (8080 aquí) para acceder a su servidor en un puerto diferente:

      • docker run --detach --restart=always --volume=thunderbird-data:/data --net=thunderbird-net --name=thunderbird-web --env=APP_USERNAME="myuser" --env=APP_PASSWORD_HASH="mypass-hash" --publish=8080:8080 thunderbird-caddy

      Ahora está listo para acceder y probar nuestra aplicación.

      Paso 6: Probar y administrar la aplicación

      Vamos a acceder a su aplicación y a asegurarnos de que está funcionando.

      Primero, abra http://your_server_ip:8080 en un navegador web, inicie sesión con las credenciales que seleccionó anteriormente y haga clic en Connect.

      Página de conexión de NoVNC

      Ahora debería poder interactuar con la aplicación, y debería cambiar de tamaño automáticamente para que se adapte a la ventana de su navegador.

      Menú principal de Thunderbird

      Si hace clic con el botón derecho en el escritorio en negro, debería ver un menú que le permite acceder a un terminal. Si hace clic en el centro, debería ver una lista de ventanas.

      Clic derecho en NoVNC

      Ahora abra http://your_server_ip:8080/files/ en un navegador web. Debería poder acceder a sus archivos.

      Archivo de acceso webdav a NoVNC

      Opcionalmente, puede intentar montar http://your_server_ip:8080/webdav/ en un cliente WebDAV. Debería poder acceder y modificar sus archivos directamente. Si utiliza la opción Asignar unidad de red en Windows Explorer, necesitará usar un proxy inverso para añadir HTTPS o establecer HKLMSYSTEMCurrentControlSetServicesWebClientParametersBasicAuthLevel​​​ a DWORD:2.

      En cualquier caso, su aplicación GUI nativa está ahora lista para su uso remoto.

      Conclusión

      Ahora ha configurado correctamente un contenedor Docker para Thunderbird y a continuación, usando Caddy, ha configurado el acceso a él a través de un navegador web. Si alguna vez necesita actualizar su aplicación, detenga los contenedores, ejecute docker rm thunderbird-app thunderbird-web, vuelva a crear las imágenes, y vuelva a ejecutar los comandos docker run de los pasos anteriores. Sus datos se conservarán, ya que se almacenan en un volumen.

      Si desea obtener más información sobre los comandos Docker básicos, puede leer este tutorial o esta hoja de trucos. Para un uso a más largo plazo, quizá desee considerar habilitar HTTPS (esto requiere un dominio) para mayor seguridad.

      Además, si está implementando más de una aplicación, es posible que desee usar Docker Compose o Kubernetes en vez de iniciar cada contenedor manualmente. Y recuerde, este tutorial puede servir como base para ejecutar cualquier otra aplicación Linux en su servidor, incluyendo:

      • Wine, una capa de compatibilidad para ejecutar aplicaciones Windows en Linux.
      • GIMP, un editor de imágenes de código abierto.
      • Cutter, una plataforma de ingeniería inversa de código abierto:

      Esta última opción demuestra el gran potencial de usar contendores y acceder remotamente a aplicaciones GUI. Con esta configuración, puede usar un servidor con una potencia de computación considerablemente mayor que si utilizase localmente herramientas que consumen muchos recursos como Cutter.



      Source link