One place for hosting & domains

      desarrollo

      Cómo usar Visual Studio Code para desarrollo remoto a través del complemento Remote-SSH


      Introducción

      Visual Studio Code es un entorno de desarrollo integrado (IDE) popular para desarrolladores. Su gran selección de complementos, su diseño minimalista y la compatibilidad con diferentes plataformas hacen que sea una excelente opción para desarrolladores de todos los niveles. Este tutorial se centra en el uso del complemento Remote-SSH para habilitar el desarrollo remoto de software. Con este complemento, puede editar archivos en su estación de trabajo local y, a la vez, llevar adelante tareas de desarrollo como la ejecución de programas, pruebas de unidad o análisis estáticos en un servidor remoto.

      Hay muchas razones por las cuales esto puede ser beneficioso. Por ejemplo, es posible que tenga una estación de trabajo de Windows y desee realizar desarrollos con Windows, y que su código eventualmente funcione en Linux. Puede necesitar más memoria RAM o potencia de procesamiento que la que tiene su equipo actual, o querer mantener el código fuera de su equipo personal debido a una política empresarial o al deseo de mantener su estación de trabajo libre.

      A través de este tutorial, habilitará el complemento Remote-SSH, configurará Visual Studio Code para ejecutar código en el servidor remoto y ejecutará código desde su instalación local de Visual Studio Code en el servidor remoto.

      Requisitos previos

      Para seguir esta guía, necesitará lo siguiente:

      • Un equipo de desarrollo local con Windows, macOSX o Linux. Este tutorial no se aplica a dispositivos Chrome OS.
      • Visual Studio Code; puede descargarlo e instalarlo desde el sitio web oficial.
      • Un par de claves SSH generadas:
      • Un servidor Ubuntu 18.04 configurado siguiendo la guía de configuración inicial del servidor Ubuntu 18.04, incluyendo un usuario sudo no root y un firewall.

      Paso 1: Instalar el complemento Remote-SSH

      En el Mercado de extensiones, puede descargar extensiones compatibles y de terceros para diferentes herramientas y lenguajes de programación. Aquí buscará e instalará el complemento Remote-SSH.

      En el lado izquierdo del IDE hay una fila vertical de cinco iconos. El icono inferior (diseño de cuatro cuadrados en forma de cuadro, cuyo cuadrado superior derecho está apartado) es el del Mercado de extensiones:

      Ubicación del icono del Mercado de extensiones

      También puede acceder a esta sección pulsando Ctrl+Shift+X. Al abrir esta página, verá los complementos sugeridos para la descarga e instalación.

      Una vez que abra el Mercado de extensiones, escriba Remote-SSH en la barra de búsqueda de extensiones. Cuando encuentre el complemento, selecciónelo y luego haga clic en el botón verde Install para instalar la extensión.

      Búsqueda del complemento Remote-SSH

      La extensión quedará instalada. A continuación, configurará la extensión para poder establecer conexión con su servidor.

      Paso 2: Configurar el complemento Remote-SSH y establecer conexión con su servidor

      Ahora que instaló el complemento, puede configurarlo para establecer conexión con un servidor. Para hacerlo, necesitará la siguiente información:

      • El IP o el nombre de host del servidor.
      • El nombre de usuario con el que se conectará.
      • La clave privada que usará para autenticar su usuario.

      Usará esta información para crear un archivo de configuración de SSH que Visual Studio Code pueda usar para establecer una conexión SSH con el servidor, y así sincronizar archivos y ejecutar código en representación de usted. Creará esta configuración usando Visual Studio Code.

      Ahora que instaló el complemento Remote-SSH, verá un pequeño cuadro verde en la esquina inferior izquierda de la interfaz de Visual Studio Code. Si posa el mouse sobre el cuadro, se abrirá un elemento emergente con la leyenda Open a remote window. El botón tiene un signo “mayor que” ligeramente por debajo de un signo “menor que”, ><, como se muestra en la siguiente imagen:

      Botón verde de abrir una ventana remota de la IU

      Haga clic en el botón. Se mostrará un cuadro de diálogo en la parte superior central. Seleccione Remote-SSH: Open Configurar File… de la lista:

      Selección de configuración de SSH en la IU

      En el siguiente mensaje, se le preguntará qué archivo de configuración desea abrir. Si usa Windows, verá dos ubicaciones: una en su directorio personal de usuario y otra en el lugar de instalación de SSH. Al configurar el servidor, debe usar el archivo que se encuentra en el directorio de su usuario.

      Seleccione el archivo. Su editor abrirá el archivo config. Añada el siguiente código al archivo para definir la conexión con su servidor y sustituya las secciones resaltadas por la información de su servidor:

      config

      Host my_remote_server
          HostName your_server_ip_or_hostname
          User sammy
          IdentityFile /location/of/your/private/key
      

      Así es como funciona este archivo de configuración:

      • Host: especifica un nombre para su host. Esto le permite usar un nombre o una abreviatura en lugar de la dirección IP o el nombre de host completos cuando establezca conexión con el servidor.
      • HostName: nombre de host real del servidor, que es una dirección IP o un nombre de dominio plenamente cualificado.
      • User: usuario que desea usar para establecer conexión.
      • IdentityFile: ruta a su clave SSH privada. En los sistemas Mac y Linux, la encontrará en su directorio de inicio, en un directorio .ssh oculto que por lo general lleva el nombre id_rsa. Si usa Windows, habrá especificado una ubicación para guardar este archivo cuando lo creó usando putty-gen.

      Especifique los valores correspondientes en su archivo y guárdelo.

      De esta manera, Visual Studio Code quedará configurado y listo para establecer conexión con su servidor. Haga clic en el botón verde Open a remote window, en la esquina inferior izquierda, y seleccione Remote-SSH: Connect to host…

      Establecer conexión con el servidor desde Visual Studio Code

      Una vez que lo haga, todos los servidores disponibles y configurados se mostrarán en el menú desplegable. Seleccione el servidor con el que desea establecer conexión en esta lista.

      Si es la primera vez que establece conexión con el servidor desde su equipo, es probable que se muestre un cuadro de diálogo de verificación de la huella digital SSH, como el que aparece en la siguiente imagen:

      Confirmar su huella digital SSH

      Esto sirve para verificar que se establezca conexión con el servidor que desea. Puede hacerlo iniciando sesión en su servidor y ejecutando ssh-keygen -l -f /etc/ssh/ssh_host_key.pub para ver la huella digital del servidor. Si esta huella es la misma que la que se muestra en Visual Studio Code, efectivamente estará estableciendo conexión con el servidor que desea. Por lo tanto, podrá hacer clic en Continue.

      Visual Studio Code abre una nueva ventana por defecto cuando se realiza una nueva conexión. Se abrirá una ventana nueva con la pantalla de bienvenida. Si la conexión se estableció de forma correcta, verá SSH: your_ip_address_or_hostname en el cuadro verde de la esquina inferior izquierda. Esto significa que Visual Studio Code está conectado y se comunica con su servidor remoto.

      Conexión correcta de SSH

      Ahora que estableció la conexión, podrá ejecutar comandos y códigos desde su editor.

      Paso 3: Ejecutar código en el servidor remoto

      Ahora que el complemento Remote-SSH está configurado, es el momento de ejecutar código en su equipo remoto. Abra una ventana de terminal seleccionando Terminal, en la barra de navegación situada en la parte superior de la ventana de Visual Studio, y haciendo clic en New Terminal. También puede abrir una terminal presionando CTRL+Shift+`. La terminal que se abre corresponde a su servidor remoto, no a su equipo local.

      Cuando se abra la terminal, ejecute el siguiente comando para ver la dirección IP de su servidor y verificar que esté conectado a su servidor remoto:

      Verá el siguiente resultado en su terminal:

      Output

      1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 16:cb:05:5b:30:f1 brd ff:ff:ff:ff:ff:ff inet your_server_ip brd your_broadcast_address scope global eth0 valid_lft forever preferred_lft forever ...

      Para probar la capacidad de ejecutar código de forma remota, cree un nuevo archivo de Python denominado hello.py en su editor. Cuando establezca conexión con su servidor remoto, todos los archivos creados a través de Visual Studio Code se guardarán en ese servidor, no en su equipo local.

      Añada el siguiente contenido al archivo:

      hello.py

      print("Hello Sammy!")
      

      Para ejecutar este programa en su servidor, abra una terminal en Visual Studio Code desde el menú de navegación o mediante la secuencia de teclas CTRL+Shift+`. Debido a que esta sesión de la terminal está conectada a su servidor remoto, debe implementar el siguiente comando en la terminal para ejecutar su programa hello.py:

      Se mostrará el resultado de su programa.

      Ejecutar su script de Python

      También puede ejecutar el archivo desde el menú contextual Debug seleccionando Run without Debugging.

      Nota: Si instaló extensiones de desarrollo en Visual Studio Code, como la de Python, deberá volver a instalarlas en su servidor a través del Mercado de extensiones. Si instaló estos complementos en Visual Studio Code previamente, cuando los vuelva a buscar, en la sección del Mercado se mostrará el mensaje Install on SSH: hostname. Siempre preste atención al contexto de desarrollo en el que se encuentre, ya que en él Visual Studio Code instalará sus complementos y creará sus archivos. Si intenta ejecutar su código sin haber instalado estos complementos, en la esquina inferior derecha de la pantalla se mostrarán cuadros de diálogo de error en los que se solicitará instalarlos en su servidor remoto. Una vez que los instale, es probable que deba volver a cargar Visual Studio Code. Cuando vuelva a iniciarlo, seguirá trabajando en el servidor remoto sin necesidad de volver a establecer conexión manualmente.

      Conclusión

      De esta manera, habrá configurado Visual Studio Code para realizar tareas de desarrollo en un servidor remoto con SSH. La ejecución remota con un IDE proporciona muchos beneficios. Entre ellos, la capacidad de probar rápidamente la forma en que su código se ejecuta en distintos sistemas operativos y con diferentes especificaciones de hardware. Mientras disponga de una conexión a Internet, podrá conectarse a su servidor y trabajar en su código desde cualquier computadora además de realizar tareas de desarrollo usando un entorno de Linux aun cuando Windows sea su sistema operativo principal.



      Source link

      Cómo disponer en contenedor una aplicación de Ruby on Rails para el desarrollo con Docker Compose


      Introducción

      Si desarrolla activamente una aplicación, usando Docker, puede simplificar su flujo de trabajo y el proceso de implementación de su aplicación para producción. El trabajo con contenedores en tareas de desarrollo tiene los siguientes beneficios:

      • Los entornos son uniformes, lo cual significa que puede elegir los lenguajes y las dependencias que desee para su proyecto sin tener que preocuparse por posibles conflictos del sistema.
      • Los entornos están aislados. Esto facilita la resolución de problemas y la admisión de nuevos miembros del equipo.
      • Los entornos son portátiles; esto permite empaquetar y compartir su código con otros.

      A través de este tutorial, verá la forma de configurar un entorno de desarrollo para una aplicación de Ruby on Rails usando Docker. Con Docker Compose, creará varios contenedores para la propia aplicación, la base de datos de PostgreSQL, Redis y un servicio Sidekiq. La configuración hará lo siguiente:

      • Sincronizar el código de la aplicación del host con el código del contenedor para facilitar los cambios durante el desarrollo.
      • Conservar los datos de la aplicación entre reinicios del contenedor.
      • Configurar trabajadores de Sidekiq para que procesen las tareas como se espera

      Al finalizar este tutorial, contará con una aplicación de información sobre tiburones en funcionamiento en contenedores de Docker:

      Inicio de la aplicación de Sidekiq

      Requisitos previos

      Para este tutorial, necesitará lo siguiente:

      Paso 1: Clonar el proyecto y agregar dependencias

      Nuestro primer paso será clonar el repositorio de rails-sidekiq de la cuenta de GitHub comunitaria de DigitalOcean. En este repositorio se incluye el código de la configuración descrita en el artículo Cómo agregar Sidekiq y Redis a una aplicación de Ruby on Rails, en el que se explica la forma de añadir Sidekiq a un proyecto de Rails 5 existente.

      Clone el repositorio en un directorio llamado rails-docker:

      • git clone https://github.com/do-community/rails-sidekiq.git rails-docker

      Diríjase al directorio rails-docker​​​:

      En este tutorial, usaremos PostgreSQL como base de datos. Para trabajar con PostgreSQL en lugar de SQLite 3, deberá añadir la gema pg a las dependencias del proyecto, que se enumeran en su Gemfile. Abra ese archivo para la edición usando nano o su editor favorito:

      Añada la gema en cualquier punto de las dependencias del proyecto principal (encima de las dependencias de desarrollo):

      ~/rails-docker/Gemfile

      . . .
      # Reduces boot times through caching; required in config/boot.rb
      gem 'bootsnap', '>= 1.1.0', require: false
      gem 'sidekiq', '~>6.0.0'
      gem 'pg', '~>1.1.3'
      
      group :development, :test do
      . . .
      

      También se puede excluir la gema sqlite, ya que dejaremos de usarla:

      ~/rails-docker/Gemfile

      . . .
      # Use sqlite3 as the database for Active Record
      # gem 'sqlite3'
      . . .
      

      Por último, excluya la gema spring-watcher-listen en development:

      ~/rails-docker/Gemfile

      . . .
      gem 'spring'
      # gem 'spring-watcher-listen', '~> 2.0.0'
      . . .
      

      Si no desactivamos esta gema, veremos mensajes de error persistentes al acceder a la consola de Rails. Estos mensajes de error derivan del hecho de que esta gema hace que Rails use listen para mantenrse informado sobre cambios en el desarrollo, en lugar de sondear el sistema de archivos en busca de cambios. Debido a que esta gema supervisa la raíz del proyecto, incluido el directorio node_modules, emitirá mensajes de error sobre los directorios controlados, lo que sobrecargará la consola. Sin embargo, si se ocupa de conservar los recursos de CPU, es posible que la desactivación de esta gema no funcione para usted. En este caso, puede ser recomendable actualizar su aplicación de Rails a Rails 6.

      Guarde y cierre el archivo cuando concluya la edición.

      Una vez que se establezca el repositorio de su proyecto, se añada la gema pg a su Gemfile y se excluya la gema spring-watcher-listen, estará listo para configurar su aplicación y trabajar con PostgreSQL.

      Paso 2: Configurar la aplicación para que funcione con PostgreSQL y Redis

      Para trabajar con PostgreSQL y Redis en proyectos de desarrollo, nos convendrá hacer lo siguiente:

      • Configurar la aplicación para que funcione con PostgreSQL como adaptador predeterminado.
      • Añadir un archivo .env al proyecto con el nombre de usuario y la contraseña de nuestra base de datos y el host de Redis.
      • Crear una secuencia de comandos init.sql a fin de generar un usuario sammy para la base de datos.
      • Añadir un inicializador para Sidekiq, de modo que pueda funcionar con nuestro servicio redis en contenedor.
      • Añadir el archivo .env y otros archivos pertinentes a los archivos gitignore y dockerignore del proyecto.
      • Crear semillas de base de datos para que nuestra aplicación tenga algunos registros con los que podamos trabajar cuando la iniciemos.

      Primero, abra el archivo de configuración de su base de datos, ubicado en config/database.yml:

      Actualmente, en el archivo se incluye la siguiente configuración predeterminada, que se aplica en caso de que no haya otra disponible:

      ~/rails-docker/config/database.yml

      default: &default
        adapter: sqlite3
        pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
        timeout: 5000
      

      Debemos cambiarla para que refleje el hecho de que usaremos el adaptador postgresql, ya que crearemos un servicio PostgreSQL con Docker Compose para conservar los datos de nuestra aplicación.

      Elimine el código que establece SQLite como adaptador y sustitúyalo por la siguiente configuración, que acondicionará el adaptador de forma adecuada junto con las demás variables necesarias para establecer conexión:

      ~/rails-docker/config/database.yml

      default: &default
        adapter: postgresql
        encoding: unicode
        database: <%= ENV['DATABASE_NAME'] %>
        username: <%= ENV['DATABASE_USER'] %>
        password: <%= ENV['DATABASE_PASSWORD'] %>
        port: <%= ENV['DATABASE_PORT'] || '5432' %>
        host: <%= ENV['DATABASE_HOST'] %>
        pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
        timeout: 5000
      . . .
      

      A continuación, modificaremos la configuración del entorno development, ya que este es el entorno que usaremos en esta configuración.

      Elimine la configuración de base de datos de SQLite existente de modo que la sección tenga el siguiente aspecto:

      ~/rails-docker/config/database.yml

      . . .
      development:
        <<: *default
      . . .
      

      Por último, elimine la configuración de database para los entornos production y test:

      ~/rails-docker/config/database.yml

      . . .
      test:
        <<: *default
      
      production:
        <<: *default
      . . .
      

      Estas modificaciones de la configuración de nuestra base de datos predeterminada nos permitirán establecer la información de nuestra base de datos de forma dinámica usando variables de entorno definidas en los archivos .env, que no se asignarán al control de versiones.

      Guarde y cierre el archivo cuando concluya la edición.

      Tenga en cuenta que si crea un proyecto de Rails desde cero, puede configurar el adaptador con el comando de rails new, como se indica en el Paso 3 de Cómo usar PostgreSQL con su aplicación de Ruby on Rails en Ubuntu 18.04. De esta forma, su adaptador quedará configurado en config/database.yml y se agregará automáticamente la gema pg al proyecto.

      Ahora que hicimos referencia a nuestras variables de entorno, podemos crear un archivo para ellas con nuestra configuración preferida. Extraer ajustes de configuración de esta manera forma parte del enfoque de 12 factores para el desarrollo de aplicaciones, que define las prácticas recomendadas para lograr resiliencia en aplicaciones en entornos distribuidos. Ahora, cuando configuremos nuestro entorno de producción y prueba en el futuro, definir los ajustes de nuestra base de datos implicará crear archivos adicionales .env y hacer referencia al archivo correspondiente de nuestros archivos de Docker Compose.

      Abra un archivo .env:

      Añada los siguientes valores al archivo:

      ~/rails-docker/.env

      DATABASE_NAME=rails_development
      DATABASE_USER=sammy
      DATABASE_PASSWORD=shark
      DATABASE_HOST=database
      REDIS_HOST=redis
      

      Además de establecer el nombre, el usuario y la contraseña de nuestra base de datos, fijamos un valor para DATABASE_HOST. El valor, database, hace referencia al servicio database de PostgreSQL que crearemos con Docker Compose. También configuramos un REDIS_HOST para especificar nuestro servicio de redis.

      Guarde y cierre el archivo cuando concluya la edición.

      Para crear el usuario de base de datos sammy, podemos escribir una secuencia de comandos init.sql que podemos montar en el contenedor de base de datos cuando se inicia.

      Abra el archivo de secuencia de comandos:

      Añada el siguiente código para crear un usuario sammy con privilegios administrativos:

      ~/rails-docker/init.sql

      CREATE USER sammy;
      ALTER USER sammy WITH SUPERUSER;
      

      Esta secuencia de comandos creará el usuario apropiado en la base de datos y otorgará a este privilegios administrativos.

      Establezca los permisos apropiados en la secuencia de comandos:

      A continuación, configuraremos Sidekiq para que funcione con nuestro servicio de redis en contenedor. Podemos añadir un inicializador al directorio config/initializers, en el que Rails busca ajustes de configuración una vez que se cargan los marcos y los complementos, con lo cual se establece un valor para un host de Redis.

      Abra un archivo sidekiq.rb para especificar estas configuraciones:

      • nano config/initializers/sidekiq.rb

      Añada el siguiente código al archivo para especificar valores de REDIS_HOST y REDIS_PORT:

      ~/rails-docker/config/initializers/sidekiq.rb

      Sidekiq.configure_server do |config|
        config.redis = {
          host: ENV['REDIS_HOST'],
          port: ENV['REDIS_PORT'] || '6379'
        }
      end
      
      Sidekiq.configure_client do |config|
        config.redis = {
          host: ENV['REDIS_HOST'],
          port: ENV['REDIS_PORT'] || '6379'
        }
      end
      

      Al igual que los ajustes de configuración de nuestra base de datos, estos ajustes nos permiten establecer los parámetros de hosts y puertos de forma dinámica, lo cual nos permite sustituir los valores apropiados en el tiempo de ejecución sin necesidad de modificar el propio código de la aplicación. Además de un REDIS_HOST, tenemos un valor predeterminado establecido para REDIS_PORT en caso de que no esté configurado en otro lugar.

      Guarde y cierre el archivo cuando concluya la edición.

      A continuación, para garantizar que los datos confidenciales de nuestra aplicación no se copien al control de versiones, podemos añadir .env al archivo .gitignore de nuestro proyecto, lo cual indica a Git los archivos que se deben ignorar en nuestro proyecto. Abra el archivo para editarlo:

      En la parte inferior del archivo, añada una entrada para .env:

      ~/rails-docker/.gitignore

      yarn-debug.log*
      .yarn-integrity
      .env
      

      Guarde y cierre el archivo cuando concluya la edición.

      A continuación, crearemos un archivo .dockerignore para establecer lo que no debe copiarse a nuestros contenedores. Abra el archivo para editarlo:

      Añada al archivo el siguiente código, el cual indica a Docker que ignore algunas de las cosas que no necesitamos copiar a nuestros contenedores:

      ~/rails-docker/.dockerignore

      .DS_Store
      .bin
      .git
      .gitignore
      .bundleignore
      .bundle
      .byebug_history
      .rspec
      tmp
      log
      test
      config/deploy
      public/packs
      public/packs-test
      node_modules
      yarn-error.log
      coverage/
      

      Añada .env al final de este archivo:

      ~/rails-docker/.dockerignore

      . . .
      yarn-error.log
      coverage/
      .env
      

      Guarde y cierre el archivo cuando concluya la edición.

      Como paso final, crearemos algunos datos semilla de modo que nuestra aplicación tenga algunos registros cuando la iniciemos.

      Abra un archivo para los datos semilla del directorio db:

      Añada el siguiente código al archivo para crear cuatro tiburones y una publicación de muestra:

      ~/rails-docker/db/seeds.rb

      # Adding demo sharks
      sharks = Shark.create([{ name: 'Great White', facts: 'Scary' }, { name: 'Megalodon', facts: 'Ancient' }, { name: 'Hammerhead', facts: 'Hammer-like' }, { name: 'Speartooth', facts: 'Endangered' }])
      Post.create(body: 'These sharks are misunderstood', shark: sharks.first)
      

      Estos datos semilla crearán cuatro tiburones y una publicación asociada al primero.

      Guarde y cierre el archivo cuando concluya la edición.

      Una vez que configure su aplicación para que funcione con PostgreSQL y cree sus variables de entorno, estará listo para escribir el Dockerfile de su aplicación.

      Paso 3: Escribir las secuencias de comandos de Dockerfile y puntos de entrada.

      Su Dockerfile especifica lo que se incluirá en el contenedor de su aplicación cuando se cree. Usar Dockerfile le permite definir el entorno de su contenedor y evitar discrepancias con las dependencias o versiones de tiempo de ejecución.

      Siguiendo estas directrices sobre la creación de contenedores optimizados, haremos que nuestra imagen sea lo más eficiente posible usando una base de Alpine e intentando minimizar las capas de nuestra imagen en general.

      Abra un Dockerfile en su directorio actual:

      Las imágenes de Docker se crean usando una sucesión de imágenes en capas que se acumulan unas sobre otras. El primer paso será añadir la imagen de base para nuestra aplicación, que formará el punto de partida de la compilación de la aplicación.

      Añada el siguiente código al archivo para agregar la imagen alpine de Ruby como base:

      ~/rails-docker/Dockerfile

      FROM ruby:2.5.1-alpine
      

      La imagen alpine se deriva del proyecto Alpine Linux, y nos ayudará a mantener el tamaño de las imágenes bajo. Para obtener más información sobre si la imagen alpine es la opción correcta para su proyecto, consulte la discusión completa en la sección de variantes de imagen de la página de imágenes de Ruby de Docker Hub.

      Algunos factores que es necesario tener en cuenta a la hora de usar alpine para el desarrollo:

      • Una imagen de tamaño reducido hará que se acorten los tiempos de carga de páginas y recursos, en particular si también mantiene los volúmenes en valores mínimos. Esto le permite lograr una experiencia de usuario de desarrollo rápida y más cercana a la que habría disponible si trabajara a nivel local en un entorno no dispuesto en contenedor.
      • La paridad entre imágenes de desarrollo y producción facilita la implementación correcta. Debido a que en los equipos se suele optar por usar imágenes de Alpine en la producción para lograr beneficios en términos de velocidad, el desarrollo con una base de Alpine ayuda a resolver problemas al realizar la transición hacia la producción.

      A continuación, establezca una variable de entorno para especificar la versión de Bundler:

      ~/rails-docker/Dockerfile

      . . .
      ENV BUNDLER_VERSION=2.0.2
      

      Este es uno de los pasos que daremos para evitar conflictos de versiones entre la versión predeterminada de bundler disponible en nuestro entorno y el código de nuestra aplicación, que requiere de Bundler 2.0.2.

      A continuación, añada al Dockerfile los paquetes que necesita para trabajar con la aplicación:

      ~/rails-docker/Dockerfile

      . . .
      RUN apk add --update --no-cache 
            binutils-gold 
            build-base 
            curl 
            file 
            g++ 
            gcc 
            git 
            less 
            libstdc++ 
            libffi-dev 
            libc-dev 
            linux-headers 
            libxml2-dev 
            libxslt-dev 
            libgcrypt-dev 
            make 
            netcat-openbsd 
            nodejs 
            openssl 
            pkgconfig 
            postgresql-dev 
            python 
            tzdata 
            yarn
      

      Entre estos paquetes se incluyen nodejs y yarn. Debido a que nuestra aplicación proporciona activos con webpack, debemos incluir Node.js y Yarn para que funcione como se espera.

      Tenga en cuenta que el contenido de la imagen alpine es extremadamente reducido: los paquetes que se mencionan aquí no contemplan por completo lo que usted podría desear o necesitar durante el desarrollo, cuando disponga en un contenedor su propia aplicación.

      A continuación, instale la versión de bundler apropiada:

      ~/rails-docker/Dockerfile

      . . .
      RUN gem install bundler -v 2.0.2
      

      Este paso garantizará la paridad entre nuestro entorno en contenedor y las especificaciones del archivo Gemfile.lock de este proyecto.

      Ahora, establezca el directorio de trabajo para la aplicación en el contenedor:

      ~/rails-docker/Dockerfile

      . . .
      WORKDIR /app
      

      Copie su Gemfile y Gemfile.lock:

      ~/rails-docker/Dockerfile

      . . .
      COPY Gemfile Gemfile.lock ./
      

      Si se copian estos archivos como paso independiente y luego se aplica bundle install, no es necesario volver a compilar las gemas del proyecto cada vez que se hacen cambios en el código de su aplicación. Esto funcionará junto con el volumen de gema que incluiremos en nuestro archivo Compose, que montará gemas en el contenedor de su aplicación en los casos en que se vuelva a crear el servicio, pero las gemas del proyecto siguen siendo iguales.

      A continuación, establezca las opciones de configuración para la compilación de la gema nokogiri:

      ~/rails-docker/Dockerfile

      . . .
      RUN bundle config build.nokogiri --use-system-libraries
      . . .
      

      Con este paso se crea nokigiri con las versiones de bibliotecas libxml2 y libxslt que añadimos al contenedor de la aplicación en el paso anterior con apk RUN add

      A continuación, instale las gemas del proyecto:

      ~/rails-docker/Dockerfile

      . . .
      RUN bundle check || bundle install
      

      Antes del proceso, esta instrucción verifica que las gemas no estén ya instaladas.

      A continuación, repetiremos el mismo procedimiento que usamos con gemas con nuestros paquetes y dependencias de JavaScript. Primero, copiaremos los metadatos de paquetes, luego instalaremos dependencias y, por último, copiaremos el código de la aplicación a la imagen del contenedor.

      Para comenzar con la sección Javascript de nuestro Dockerfile, copie el package.json y yarn.lock desde el directorio de su proyecto actual del host al contenedor:

      ~/rails-docker/Dockerfile

      . . .
      COPY package.json yarn.lock ./
      

      A continuación instale los paquetes necesarios con yarn install:

      ~/rails-docker/Dockerfile

      . . .
      RUN yarn install --check-files
      

      Esta instrucción incluye una bandera --check-files con el comando yarn, una función que garantiza que no se hayan eliminado archivos previamente instalados. Como en el caso de nuestras gemas, administraremos la persistencia de los paquetes en el directorio node_modules con un volumen cuando escribamos nuestro archivo Compose.

      Por último, copie el resto del código de la aplicación e iniícela con una secuencia de comandos de punto de entrada:

      ~/rails-docker/Dockerfile

      . . .
      COPY . ./
      
      ENTRYPOINT ["./entrypoints/docker-entrypoint.sh"]
      

      El uso de una secuencia de comandos de punto de entrada nos permite ejecutar el contenedor como un ejecutable.

      El Dockerfile final tendrá el siguiente aspecto:

      ~/rails-docker/Dockerfile

      FROM ruby:2.5.1-alpine
      
      ENV BUNDLER_VERSION=2.0.2
      
      RUN apk add --update --no-cache 
            binutils-gold 
            build-base 
            curl 
            file 
            g++ 
            gcc 
            git 
            less 
            libstdc++ 
            libffi-dev 
            libc-dev 
            linux-headers 
            libxml2-dev 
            libxslt-dev 
            libgcrypt-dev 
            make 
            netcat-openbsd 
            nodejs 
            openssl 
            pkgconfig 
            postgresql-dev 
            python 
            tzdata 
            yarn
      
      RUN gem install bundler -v 2.0.2
      
      WORKDIR /app
      
      COPY Gemfile Gemfile.lock ./
      
      RUN bundle config build.nokogiri --use-system-libraries
      
      RUN bundle check || bundle install
      
      COPY package.json yarn.lock ./
      
      RUN yarn install --check-files
      
      COPY . ./
      
      ENTRYPOINT ["./entrypoints/docker-entrypoint.sh"]
      

      Guarde y cierre el archivo cuando concluya la edición.

      A continuación, cree un directorio llamado entry points para las secuencias de comandos de punto de entrada:

      En este directorio se incluirán nuestra secuencia de comandos de punto de entrada principal y una secuencia de comandos para nuestro servicio Sidekiq.

      Abra el archivo de la secuencia de comandos de punto de entrada de la aplicación:

      • nano entrypoints/docker-entrypoint.sh

      Añada el siguiente código al archivo:

      rails-docker/entrypoints/docker-entrypoint.sh

      #!/bin/sh
      
      set -e
      
      if [ -f tmp/pids/server.pid ]; then
        rm tmp/pids/server.pid
      fi
      
      bundle exec rails s -b 0.0.0.0
      

      La primera línea importante es set -e, e indica al shell /bin/sh que ejecuta la secuencia de comandos que genere un fallo inmediato si hay problemas más adelante en la secuencia de comandos. A continuación, la secuencia de comandos verifica que tmp/pids/server.pid no esté presente para garantizar que no se produzcan conflictos de servidores cuando iniciemos la aplicación. Por último, la secuencia de comandos inicia el servidor de Rails con el comando bundle exec rails s. Usamos la opción -b con este comando para vincular el servidor a todas las direcciones IP y no a la predeterminada, localhost. Esta invocación hace que el servidor de Rails dirija las solicitudes a la dirección IP del contenedor en lugar de usar el localhost predeterminado.

      Guarde y cierre el archivo cuando concluya la edición.

      Haga que la secuencia de comandos sea ejecutable:

      • chmod +x entrypoints/docker-entrypoint.sh

      A continuación, crearemos una secuencia de comandos para iniciar nuestro servicio sidekiq que procesará nuestros trabajos de Sidekiq. Para obtener más información sobre la forma en que esta aplicación usa Sidekiq, consulte Cómo agregar Sidekiq y Redis a una aplicación de Ruby on Rails.

      Abra un archivo para la secuencia de comandos de punto de entrada de Sidekiq:

      • nano entrypoints/sidekiq-entrypoint.sh

      Añada el siguiente código al archivo para iniciar Sidekiq:

      ~/rails-docker/entrypoints/sidekiq-entrypoint.sh

      #!/bin/sh
      
      set -e
      
      if [ -f tmp/pids/server.pid ]; then
        rm tmp/pids/server.pid
      fi
      
      bundle exec sidekiq
      

      Esta secuencia de comandos inicia Sidekiq en el contexto de nuestro paquete de aplicaciones.

      Guarde y cierre el archivo cuando concluya la edición. Haga que sea ejecutable:

      • chmod +x entrypoints/sidekiq-entrypoint.sh

      Con sus secuencias de comandos de punto de entrada y Dockerfile, estará listo para definir sus servicios en su archivo de Compose.

      Paso 4: Definir servicios con Docker Compose

      Usando Docker Compose, podremos ejecutar los diferentes contenedores necesarios para nuestra configuración. Definiremos nuestros servicios de Compose en nuestro archivo docker-compose.yml principal: Un servicio en Compose es un contenedor en ejecución y las definiciones del servicio, que incluirá en su archivo docker-compose.yml, contienen información sobre cómo se ejecutará cada imagen del contenedor. La herramienta Compose le permite definir varios servicios para crear aplicaciones en diferentes contenedores.

      En la configuración de nuestra aplicación se incluirán los siguientes servicios:

      • La propia aplicación
      • La base de datos de PostgreSQL
      • Redis
      • Sidekiq

      También incluiremos un montaje bind como parte de nuestra configuración, de modo que cualquier cambio de código que hagamos durante el desarrollo se sincronice de inmediato con los contenedores que necesiten acceso a este código.

      Tenga en cuenta que no definiremos un servicio test, ya que estas encuentran fuera del alcance de este tutorial y esta serie, pero podría hacerlo siguiendo el anterior que usaremos aquí para el servicio sidekiq.

      Abra el archivo docker-compose.yml:

      Primero, añada la definición del servicio de la aplicación:

      ~/rails-docker/docker-compose.yml

      version: '3.4'
      
      services:
        app:
          build:
            context: .
            dockerfile: Dockerfile
          depends_on:
            - database
            - redis
          ports:
            - "3000:3000"
          volumes:
            - .:/app
            - gem_cache:/usr/local/bundle/gems
            - node_modules:/app/node_modules
          env_file: .env
          environment:
            RAILS_ENV: development
      

      La definición del servicio app incluye las siguientes opciones:

      • build: define las opciones de configuración, incluido el context y dockerfile, que se aplicarán cuando Compose cree la imagen de la aplicación. Si desea utilizar una imagen existente de un registro como Docker Hub, podría utilizar la instrucción image como alternativa, con información sobre su nombre de usuario, repositorio y etiqueta de imagen.
      • context: esto define el contexto de compilación para la compilación de la imagen; en este caso, el directorio del proyecto actual.
      • dockerfile: esto especifica el Dockerfile del directorio actual de su directorio como el archivo que Compose usará para complilar la imagen de la aplicación.
      • depends_on: esto establece primero database y los contenedores de redis para que estén listos y en ejecución antes que app.
      • ports: asigna el puerto 3000 del host al puerto 3000 del contenedor.
      • volumes: incluiremos dos tipos de montajes aquí:
        • El primero es un montaje bind, que monta el código de nuestra aplicación del host en el directorio /app del contenedor. Esto facilitará un desarrollo rápido, ya que cualquier cambio que realice a su código de host se completará de inmediato en el contenedor.
        • El segundo es un volumen con nombre: gem_cache. Cuando la instrucción bundle install se ejecute en el contenedor, instalará las gemas del proyecto. Añadir este volumen significa que si recrea el contenedor, las gemas se montarán en el nuevo contenedor. Para este montaje se prevé que no se produjeron cambios en el proyecto, de modo que si realiza cambios en las gemas de su proyecto, deberá recordar eliminar este volumen antes de recrear el servicio de su aplicación.
        • El tercero es un volumen con nombre para el directorio node_modules. En lugar de contar con node_modules montados en el host, que pueden generar discrepancias de paquetes y conflictos de permisos durante el desarrollo, este volumen garantizará que los paquetes de este directorio se mantengan y reflejen el estado actual del proyecto. Una vez más, si modifica las dependencias del proyecto de Node, deberá eliminar y recrear este volumen.
      • env_file: indica a Compose que deseamos añadir variables de entorno de un archivo llamado .env, ubicado en el contexto de compilación.
      • environment: usar esta opción nos permite establecer una variable de entorno no sensible y pasar información sobre el entorno de Rails al contenedor.

      A continuación, debajo de la definición del servicio app, añada el siguiente código para definir su servicio database:

      ~/rails-docker/docker-compose.yml

      . . .
        database:
          image: postgres:12.1
          volumes:
            - db_data:/var/lib/postgresql/data
            - ./init.sql:/docker-entrypoint-initdb.d/init.sql
      

      A diferencia del servicio app, el servicio database obtiene una imagen de postgres directamente del Hub de Docker. Tenga en cuenta que también anclaremos la versión aquí, en lugar de fijarla en latest o no especificarla (su valor predeterminado es latest). De esta forma, podemos garantizar que esta configuración funcione con las versiones aquí especificadas y evitar sorpresas inesperadas con cambios por código dañado en la imagen.

      Aquí, también incluiremos un volumen db_data, que conservará los datos de nuestra aplicación entre uno y otro inicio del contenedor. Además, montamos nuestra secuencia de comandos de inicio init.sql en el directorio apropiado, docker-entrypoint-initdb.d/ del contenedor, a fin de crear nuestro usuario de base de datos sammy. Después de que el punto de entrada de imagen cree el usuario y la base de datos de postgres predeterminados, ejecutará cualquier secuencia de comandos del directorio docker-entrypoint-initdb.d/ que puede usar para las tareas de inicialización necesarias. Para obtener más información, consulte la sección Secuencias de comandos de inicialización de la documentación de imagen de PostgreSQL.

      A continuación, añada la definición del servicio de redis:

      ~/rails-docker/docker-compose.yml

      . . .
        redis:
          image: redis:5.0.7
      

      Al igual que el servicio database, el servicio de redis utiliza una imagen del Hub de Docker. En este caso, no conservaremos la caché de trabajo de Sidekiq.

      Por último, añada la definición del servicio sidekiq:

      ~/rails-docker/docker-compose.yml

      . . .
        sidekiq:
          build:
            context: .
            dockerfile: Dockerfile
          depends_on:
            - app      
            - database
            - redis
          volumes:
            - .:/app
            - gem_cache:/usr/local/bundle/gems
            - node_modules:/app/node_modules
          env_file: .env
          environment:
            RAILS_ENV: development
          entrypoint: ./entrypoints/sidekiq-entrypoint.sh
      

      Nuestro servicio sidekiq se asemeja a nuestro servicio app en algunos aspectos: el contexto y la imagen de compilación, las variables de entorno y el volumen que usa son los mismos. Sin embargo, depende de los servicios app, redis y database, y se iniciará en último lugar. Además, utiliza un entrypoint que anulará el punto de entrada establecido en el Dockerfile. Este ajuste entrypoint apunta a entrypoints/sidekiq-entrypoint.sh, que incluye el comando indicado para iniciar el servicio sidekiq.

      Como paso final, añada las definiciones de volumen que se encuentran debajo de la definición del servicio sidekiq:

      ~/rails-docker/docker-compose.yml

      . . .
      volumes:
        gem_cache:
        db_data:
        node_modules:
      

      Nuestra clave de volúmenes de nivel superior define lo volúmenes gem_cache, db_data y node_modules. Cuando Docker crea volúmenes, el contenido de estos se almacena en una parte del sistema de archivos de host, /var/ib/docker/volume/, que Docker administra. El contenido de cada volumen se almacena en un directorio en /var/lib/docker/volume/ y se monta en cualquier contenedor que utilice el volumen. De esta forma, los datos sobre tiburones que nuestros usuarios crearán persistirán en el volumen db_data, incluso si eliminamos y volvemos a crear el servicio database.

      El archivo terminado tendrá este aspecto:

      ~/rails-docker/docker-compose.yml

      version: '3.4'
      
      services:
        app:
          build:
            context: .
            dockerfile: Dockerfile
          depends_on:     
            - database
            - redis
          ports:
            - "3000:3000"
          volumes:
            - .:/app
            - gem_cache:/usr/local/bundle/gems
            - node_modules:/app/node_modules
          env_file: .env
          environment:
            RAILS_ENV: development
      
        database:
          image: postgres:12.1
          volumes:
            - db_data:/var/lib/postgresql/data
            - ./init.sql:/docker-entrypoint-initdb.d/init.sql
      
        redis:
          image: redis:5.0.7
      
        sidekiq:
          build:
            context: .
            dockerfile: Dockerfile
          depends_on:
            - app      
            - database
            - redis
          volumes:
            - .:/app
            - gem_cache:/usr/local/bundle/gems
            - node_modules:/app/node_modules
          env_file: .env
          environment:
            RAILS_ENV: development
          entrypoint: ./entrypoints/sidekiq-entrypoint.sh
      
      volumes:
        gem_cache:
        db_data:
        node_modules:     
      

      Guarde y cierre el archivo cuando concluya la edición.

      Una vez escritas sus definiciones de su servicios, estará listo para iniciar la aplicación.

      Paso 5: Probar la aplicación

      Una vez implementado su archivo docker-compose.yml, puede crear sus servicios con el comando docker-compose up y propagar su base de datos. También puede comprobar que sus datos persisitirán deteniendo y eliminando sus contenedores con docker-compose down y volviendo a crearlos.

      Primero, compile las imágenes del contenedor y cree los servicios ejecutando docker-compose up con el indicador -d, que luego ejecutará los contenedores en segundo plano.

      Verá un resultado que indicará la creación de sus servicios:

      Output

      Creating rails-docker_database_1 ... done Creating rails-docker_redis_1 ... done Creating rails-docker_app_1 ... done Creating rails-docker_sidekiq_1 ... done

      También puede obtener información más detallada sobre los procesos de inicio mostrando el resultado del registro de los servicios:

      Si todo se inició de forma correcta, verá algo similar a esto:

      Output

      sidekiq_1 | 2019-12-19T15:05:26.365Z pid=6 tid=grk7r6xly INFO: Booting Sidekiq 6.0.3 with redis options {:host=>"redis", :port=>"6379", :id=>"Sidekiq-server-PID-6", :url=>nil} sidekiq_1 | 2019-12-19T15:05:31.097Z pid=6 tid=grk7r6xly INFO: Running in ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-musl] sidekiq_1 | 2019-12-19T15:05:31.097Z pid=6 tid=grk7r6xly INFO: See LICENSE and the LGPL-3.0 for licensing details. sidekiq_1 | 2019-12-19T15:05:31.097Z pid=6 tid=grk7r6xly INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org app_1 | => Booting Puma app_1 | => Rails 5.2.3 application starting in development app_1 | => Run `rails server -h` for more startup options app_1 | Puma starting in single mode... app_1 | * Version 3.12.1 (ruby 2.5.1-p57), codename: Llamas in Pajamas app_1 | * Min threads: 5, max threads: 5 app_1 | * Environment: development app_1 | * Listening on tcp://0.0.0.0:3000 app_1 | Use Ctrl-C to stop . . . database_1 | PostgreSQL init process complete; ready for start up. database_1 | database_1 | 2019-12-19 15:05:20.160 UTC [1] LOG: starting PostgreSQL 12.1 (Debian 12.1-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit database_1 | 2019-12-19 15:05:20.160 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432 database_1 | 2019-12-19 15:05:20.160 UTC [1] LOG: listening on IPv6 address "::", port 5432 database_1 | 2019-12-19 15:05:20.163 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432" database_1 | 2019-12-19 15:05:20.182 UTC [63] LOG: database system was shut down at 2019-12-19 15:05:20 UTC database_1 | 2019-12-19 15:05:20.187 UTC [1] LOG: database system is ready to accept connections . . . redis_1 | 1:M 19 Dec 2019 15:05:18.822 * Ready to accept connections

      También puede verificar el estado de sus contenedores con docker-compose ps:

      Verá un resultado que indicará que sus contenedores están en ejecución:

      Output

      Name Command State Ports ----------------------------------------------------------------------------------------- rails-docker_app_1 ./entrypoints/docker-resta ... Up 0.0.0.0:3000->3000/tcp rails-docker_database_1 docker-entrypoint.sh postgres Up 5432/tcp rails-docker_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp rails-docker_sidekiq_1 ./entrypoints/sidekiq-entr ... Up

      A continuación, cree y propague su base de datos, y ejecute migraciones en ella con el siguiente comando docker-compose exec:

      • docker-compose exec app bundle exec rake db:setup db:migrate

      El comando docker-compose exec le permite ejecutar comandos en sus servicios; lo usaremos aquí para que ejecute rake db:setup y db:migrate en el contexto del paquete de nuestra aplicación, a fin de crear y sembrar la base de datos y ejecutar migraciones. A medida que trabaje en el desarrollo, docker-compose exec será útil para usted cuando desee ejecutar migraciones con su base de datos de desarrollo.

      Verá el siguiente resultado después de ejecutar este comando:

      Output

      Created database 'rails_development' Database 'rails_development' already exists -- enable_extension("plpgsql") -> 0.0140s -- create_table("endangereds", {:force=>:cascade}) -> 0.0097s -- create_table("posts", {:force=>:cascade}) -> 0.0108s -- create_table("sharks", {:force=>:cascade}) -> 0.0050s -- enable_extension("plpgsql") -> 0.0173s -- create_table("endangereds", {:force=>:cascade}) -> 0.0088s -- create_table("posts", {:force=>:cascade}) -> 0.0128s -- create_table("sharks", {:force=>:cascade}) -> 0.0072s

      Una vez que sus servicios estén en ejecución, puede visitar localhost:3000 o http://your_server_ip:3000 en el navegador. Verá una página de aterrizaje similar a esta:

      Inicio de la aplicación de Sidekiq

      Ahora, podemos probar la persistencia de datos. Cree un nuevo tiburón haciendo clic en el botón Get Shark Info, que lo dirigirá a la ruta sharks/index:

      Página de índice de tiburones con datos propagados

      Para verificar que la aplicación funcione, podemos añadirle información de prueba. Haga clic en New Shark. Gracias a la configuración de autenticación del proyecto, se le solicitará un nombre de usuario (sammy) y una contraseña (tiburón).

      En la página New Shark, ingrese “Mako” en el campo Name y “Fast” en el campo Facts.

      Haga clic en el botón Create Shark para crear el tiburón. Una vez que haya creado el tiburón, haga clic en Home en la barra de navegación del sitio para volver a la página de aterrizaje de la aplicación. Ahora, podemos probar que Sidekiq funciona.

      Haga clic en el botón** ¿Which Sharks Are In Danger?** . Debido a que no cargó ningún tiburón en peligro, esto lo dirigirá a la vista de endangered index:

      Vista del índice de tiburones en peligro

      Haga clic en Import Endangered Sharks para importar los tiburones. Verá un mensaje de estado que le indicará que los tiburones se importaron:

      Inicio de la importación

      También verá el comienzo de la importación. Actualice su página para ver la tabla entera:

      Actualización de tabla

      Gracias a Sidekiq, realizamos la carga del gran lote de tiburones en peligro sin cerrar el navegador ni interferir con otras funciones de la aplicación.

      Haga clic en el botón Home en la parte inferior de la página, que lo llevará de vuelta a la página principal de la aplicación:

      Inicio de la aplicación de Sidekiq

      Aquí, haga clic en Which Sharks Are in Danger? nuevamente. Verá los tiburones cargados otra vez.

      Ahora que sabemos que nuestra aplicación funciona correctamente, podemos probar la persistencia de nuestros datos.

      Cuando regrese a su terminal, escriba el siguiente comando para detener y eliminar sus contenedores:

      Tenga en cuenta que no incluiremos la opción --volumes; por lo tanto, no se eliminará nuestro volumen db_data.

      El siguiente resultado confirma que se eliminaron sus contenedores y su red:

      Output

      Stopping rails-docker_sidekiq_1 ... done Stopping rails-docker_app_1 ... done Stopping rails-docker_database_1 ... done Stopping rails-docker_redis_1 ... done Removing rails-docker_sidekiq_1 ... done Removing rails-docker_app_1 ... done Removing rails-docker_database_1 ... done Removing rails-docker_redis_1 ... done Removing network rails-docker_default

      Vuelva a crear los contenedores:

      Abra la consola de Rails en el contenedor app con docker-compose exec y bundle exec rails console:

      • docker-compose exec app bundle exec rails console

      En el símbolo de sistema, inspeccione el registro last de Tiburón de la base de datos:

      Verá el registro que acaba de crear:

      IRB session

      Shark Load (1.0ms) SELECT "sharks".* FROM "sharks" ORDER BY "sharks"."id" DESC LIMIT $1 [["LIMIT", 1]] => "#<Shark id: 5, name: "Mako", facts: "Fast", created_at: "2019-12-20 14:03:28", updated_at: "2019-12-20 14:03:28">"

      Luego, puede verificar que sus tiburones endangered se hayan conservado con el siguiente comando:

      IRB session

      (0.8ms) SELECT COUNT(*) FROM "endangereds" => 73

      Su volumen db_data se montó correctamente en el servicio database recreado, lo cual posibilitó que su servicio app accediera a los datos guardados. Si accede directamente a la página index shark visitando localhost:3000/sharks o http://your_server_ip:3000/sharks, también verá el registro:

      Página de índice de tiburones con Mako

      Sus tiburones en peligro también se encontrarán en la vista localhost:3000/endangered/data o http://your_server_ip:3000/endangered/data:

      Actualización de la tabla

      Su aplicación ahora se ejecuta en los contenedores de Docker con la persistencia de datos y la sincronización de códigos habilitadas. Puede probar los cambios de código local en su host, que se sincronizarán con su contenedor gracias al montaje que definimos como parte del servicio de app.

      Conclusión

      Siguiendo este tutorial, creó una configuración de desarrollo para su aplicación de Rails usando contenedores de Docker. Hizo que su proyecto fuera más modular y portátil mediante la extracción de información confidencial y la desvinculación del estado de su aplicación de su código. También configuró un archivo docker-compose.yml estándar que podrá revisar a medida que sus necesidades y requisitos de desarrollo cambien.

      A medida que realice desarrollos, es posible que le interese aprender más sobre cómo diseñar aplicaciones para flujos de trabajo en contenedores y de Cloud Native. Consulte Crear aplicaciones para Kubernetes y Modernizar aplicaciones para Kubernetes para obtener más información sobre estos temas. O bien, si desea invertir en una secuencia de aprendizaje de Kubernetes, consulte Kubernetes para desarrolladores Full-Stack.

      Para obtener más información sobre el código de la aplicación en sí, consulte los otros tutoriales de esta serie:



      Source link

      Cómo disponer en contenedor una aplicación Laravel 6 para el desarrollo con Docker Compose en Ubuntu 18.04


      Introducción

      Cuando se habla de disponer en contenedores una aplicación, se hace referencia al proceso de adaptación de una aplicación y sus componentes para poder ejecutarla en entornos ligeros conocidos como contenedores. Estos entornos están aislados, son desechables y se pueden utilizar para desarrollar, probar e implementar aplicaciones en la producción.

      A lo largo de esta guía, utilizaremos Docker Compose para disponer en contendor una aplicación Laravel 6 para el desarrollo. Al finalizar, dispondrá de una aplicación Laravel de demostración funcional en tres contenedores de servicios separados:

      • un servicio app con PHP7.4-FPM;
      • un servicio db con MySQL 5.7;
      • un servicio nginx en el que se utilice el servicio app para analizar el código PHP antes de proporcionar la aplicación Laravel al usuario final.

      Para permitir un proceso de desarrollo simplificado y facilitar la depuración de aplicaciones, mantendremos sincronizados los archivos de la aplicación usando volúmenes compartidos. También veremos cómo usar comandos docker-compose exec para la ejecución de Composer y Artisan en el contenedor app.

      Requisitos previos

      Paso 1: Obtener la aplicación de demostración

      Para comenzar, obtendremos la aplicación Laravel de demostración de su repositorio de Github. Nos interesa la ramificación tutorial-01, que contiene la aplicación básica de Laravel que creamos en la primera guía de esta serie.

      Para obtener el código de la aplicación que es compatible con este tutorial, descargue la versión tutorial-1.0.1 en su directorio de inicio con lo siguiente:

      • cd ~
      • curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.zip

      Necesitaremos el comando unzip para desempaquetar el código de la aplicación. En caso de que no haya instalado el paquete antes, hágalo ahora con lo siguiente:

      • sudo apt update
      • sudo apt install unzip

      Luego, descomprima el contenido de la aplicación y cambie el nombre del directorio desempaquetado para facilitar el acceso:

      • unzip travellist.zip
      • mv travellist-laravel-demo-tutorial-1.0.1 travellist-demo

      Diríjase al directorio travellist-demo:

      En el siguiente paso, crearemos un archivo de configuración .env para configurar la aplicación.

      Paso 2: Configurar el archivo .env de la aplicación

      Los archivos de configuración de Laravel se encuentran en un directorio llamado config, dentro del directorio root de la aplicación. Además, un archivo .env se utiliza para establecer una configuración dependiente del entorno, como las credenciales y cualquier información que pueda variar entre las implementaciones. Este archivo no está incluido en el control de revisiones.

      Advertencia: En el archivo de configuración del entorno se encuentra información confidencial sobre su servidor, incluidas las credenciales de bases de datos y las claves de seguridad. Por ese motivo, nunca debe compartir públicamente este archivo.

      Los valores incluidos en el archivo .env tendrán prioridad sobre los valores establecidos en los archivos de configuración normales que se encuentran en el directorio config. Para cada instalación en un nuevo entorno se requiere un archivo de entorno personalizado a fin de definir elementos como las configuraciones de conexión de bases de datos, las opciones de depuración y las URL de aplicación, entre otros elementos que pueden variar dependiendo del entorno en el que se ejecute la aplicación.

      Ahora, crearemos un nuevo archivo .env para personalizar las opciones de configuración para el entorno de desarrollo que configuraremos. En Laravel se incluye un archivo .env de ejemplo que podemos copiar para crear el nuestro:

      Abra este archivo utilzando nano o el editor de texto que prefiera:

      En el archivo .env actual de la aplicación de demostración travellist se incluyen las configuraciones para usar una base de datos local de MySQL, con 127.0.0.1 como host de base de datos. Necesitamos actualizar la variable DB_HOST para que esta apunte al servicio de base de datos que crearemos en nuestro entorno de Docker. En esta guía, usaremos el nombre db para el servicio de nuestra base de datos. Sustituya el valor de la lista de DB_HOST por el nombre del servicio de la base de datos:

      .env

      APP_NAME=Travellist
      APP_ENV=dev
      APP_KEY=
      APP_DEBUG=true
      APP_URL=http://localhost:8000
      
      LOG_CHANNEL=stack
      
      DB_CONNECTION=mysql
      DB_HOST=db
      DB_PORT=3306
      DB_DATABASE=travellist
      DB_USERNAME=travellist_user
      DB_PASSWORD=password
      ...
      

      Si lo desea, puede cambiar también el nombre, el nombre de usuario y la contraseña de la base de datos. Estas variables aprovecharán en un paso posterior en el que prepararemos el archivo docker-compose.yml para configurar nuestros servicios.

      Guarde el archivo cuando finalice la edición. Si utiliza nano, puede hacerlo presionando CTRL+X, luego Y y Enter para confirmar.

      Paso 3: Configurar el Dockerfile de la aplicación

      Aunque ambos servicios de MySQL y Nginx se basarán en imágenes predeterminadas obtenidas de Docker Hub, debemos de todas formas crear una imagen personalizada para el contenedor de la aplicación. Crearemos un nuevo Dockerfile para ello.

      Nuestra imagen de travellist se basará en la imagen oficial de PHP php:7.4-fpm de Docker Hub. Además de ese entorno básico de PHP-FPM, instalaremos algunos módulos de PHP adicionales y la herramienta de administración de dependencias Composer.

      También crearemos un nuevo usuario de sistema; esto es necesario para ejecutar los comandos artisan y composer mientras se desarrolla la aplicación. En la configuración uid se garantiza que el usuario dentro del contenedor tenga el mismo uid que el usuario de su sistema en su equipo host, donde Docker está en ejecución. De esta manera, todos los archivos creados por estos comandos se replican en el host con los permisos correctos. Esto también significa que podrá usar su editor de código preferido en la máquina host para desarrollar la aplicación que está en ejecución dentro de los contenedores.

      Cree un nuevo Dockerfile con lo siguiente:

      Copie el siguiente contenido en su Dockerfile:

      Dockerfile

      FROM php:7.4-fpm
      
      # Arguments defined in docker-compose.yml
      ARG user
      ARG uid
      
      # Install system dependencies
      RUN apt-get update && apt-get install -y 
          git 
          curl 
          libpng-dev 
          libonig-dev 
          libxml2-dev 
          zip 
          unzip
      
      # Clear cache
      RUN apt-get clean && rm -rf /var/lib/apt/lists/*
      
      # Install PHP extensions
      RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
      
      # Get latest Composer
      COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
      
      # Create system user to run Composer and Artisan Commands
      RUN useradd -G www-data,root -u $uid -d /home/$user $user
      RUN mkdir -p /home/$user/.composer && 
          chown -R $user:$user /home/$user
      
      # Set working directory
      WORKDIR /var/www
      
      USER $user
      
      

      No olvide guardar el archivo cuando termine.

      Nuestro Dockerfile comienza definiendo la imagen base que usaremos: php:7.4-fpm.

      Después de instalar los paquetes del sistema y las extensiones de PHP, instalamos Composer copiando el ejecutable composer de su imagen oficial más reciente en la propia imagen de nuestra aplicación.

      A continuación, se crea un nuevo usuario de sistema y se configura usando los argumentos user y uid que se declararon al inicio del Dockerfile. Docker Compose insertará estos valores en el tiempo de compilación.

      Por último, fijaremos el directorio de trabajo predeterminado como /var/www y cambiaremos al usuario recién creado. Esto garantizará que se conecte como un usuario normal y que se encuentre en el directorio correcto, al ejecutar comandos de composer y artisan en el contenedor de la aplicación.

      Paso 4: Preparar archivos de configuración de Nginx y de volcado de bases de datos

      Cuando se crean entornos de desarrollo con Docker Compose, a menudo es necesario compartir archivos de configuración o de inicialización con contenedores de servicios para que se puedan configurar o aplicar estos servicios. Esta práctica facilita la aplicación de cambios en los archivos de configuración para ajustar el entorno mientras desarrolla la aplicación.

      Ahora crearemos una carpeta con archivos que se utilizarán para configurar e inicializar nuestros contenedores de servicios.

      Para configurar Nginx, compartiremos un archivo travellist.conf en el que se configurará la forma en que se proporciona la aplicación. Cree la carpeta docker-compose/nginx con lo siguiente:

      • mkdir -p docker-compose/nginx

      Abra un nuevo archivo llamado travellist.conf dentro de ese directorio:

      • nano docker-compose/nginx/travellist.conf

      Copie la siguiente configuración de Nginx en ese archivo:

      docker-compose/nginx/travellist.conf

      
      server {
          listen 80;
          index index.php index.html;
          error_log  /var/log/nginx/error.log;
          access_log /var/log/nginx/access.log;
          root /var/www/public;
          location ~ .php$ {
              try_files $uri =404;
              fastcgi_split_path_info ^(.+.php)(/.+)$;
              fastcgi_pass app:9000;
              fastcgi_index index.php;
              include fastcgi_params;
              fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
              fastcgi_param PATH_INFO $fastcgi_path_info;
          }
          location / {
              try_files $uri $uri/ /index.php?$query_string;
              gzip_static on;
          }
      }
      

      En este archivo se configurará Nginx para que escuche en el puerto 80 y utilice index.php como la página de índice predeterminada. Establecerá el documento root en /var/www/public y luego configurará Nginx para que en este se utilice el servicio app en el puerto 9000 a fin de procesar archivos *.php.

      Guarde y cierre el archivo cuando finalice la edición.

      Para configurar la base de datos de MySQL, compartiremos un volcado de base de datos que se importará cuando se inicialice el contenedor. Esta es una característica que se proporciona a través de la imagen de MySQL 5.7 y que usaremos en ese contenedor.

      Cree una nueva carpeta para sus archivos de inicialización de MySQL dentro de la carpeta docker-compose:

      • mkdir docker-compose/mysql

      Abra un nuevo archivo .sql:

      • nano docker-compose/mysql/init_db.sql

      El siguiente volcado de MySQL deriva de la base de datos que configuramos en nuestra guía sobre Laravel en LEMP. Se creará una nueva tabla llamada places. Luego, se completará la tabla con un conjunto de lugares de ejemplo.

      Añada el siguiente código al archivo:

      docker-compose/mysql/db_init.sql

      DROP TABLE IF EXISTS `places`;
      
      CREATE TABLE `places` (
        `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
        `visited` tinyint(1) NOT NULL DEFAULT '0',
        PRIMARY KEY (`id`)
      ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
      
      INSERT INTO `places` (name, visited) VALUES ('Berlin',0),('Budapest',0),('Cincinnati',1),('Denver',0),('Helsinki',0),('Lisbon',0),('Moscow',1),('Nairobi',0),('Oslo',1),('Rio',0),('Tokyo',0);
      

      En la tabla places se incluyen tres campos: id, name y visited. El campo visited es un indicador utilizado para identificar los lugares que aún quedan por recorrer. Puede cambiar los lugares de ejemplo o incluir casos nuevos si lo desea. Guarde y cierre el archivo cuando termine.

      Terminamos de preparar el Dockerfile de la aplicación y los archivos de configuración del servicio. A continuación, configuraremos Docker Compose para que se utilicen estos archivos al crear nuestros servicios.

      Paso 5: Crear un entorno en varios contenedores con Docker Compose

      Docker Compose le permite crear entornos en varios contenedores para aplicaciones que se ejecuten en Docker. Se utilizan definiciones de servicio para crear entornos totalmente personalizables con varios contenedores que pueden compartir redes y volúmenes de datos. Esto permite una integración sin problemas entre los componentes de la aplicación.

      Para establecer nuestras definiciones de servicios, crearemos un nuevo archivo llamado docker-compose.yml. Normalmente, este archivo se encuentra en la carpeta root de la aplicación y define su entorno en contenedor, incluidas las imágenes de base que usará para crear sus contenedores y la forma en que interactuarán sus servicios.

      Definiremos tres servicios diferentes en nuestro archivo docker-compose.yml: app, db y nginx.

      En el servicio app se creará una imagen llamada travellist, basada en el Dockerfile que creamos previamente. En el contenedor definido por este servicio se ejecutará un servidor php-fpm para analizar el código PHP y enviar los resultados de vuelta al servicio nginx, que estará en ejecución en un contenedor separado. A través del servicio mysql, se define un contenedor en un servidor MySQL 5.7. En nuestros servicios se compartirá una red de puente llamada travellist.

      Los archivos de la aplicación se sincronizarán en los servicios app y nginx mediante montajes “bind”. Los montajes “bind” son útiles en los entornos de desarrollo porque en estos se permite una sincronización bidireccional estable entre el equipo host y los contenedores.

      Cree un nuevo archivo docker-compose.yml en la carpeta root de la aplicación:

      Un archivo típico de docker-compose.yml comienza con una definición de versión, a la que le sigue un nodo services, donde se definen todos los servicios. Las redes compartidas suelen definirse al final de ese archivo.

      Para comenzar, copie el siguiente código estándar a su archivo docker-compose.yml:

      docker-compose.yml

      version: "3.7"
      services:
      
      
      networks:
        travellist:
          driver: bridge
      

      Ahora, editaremos el nodo services para incluir los servicios app, db y nginx.

      El servicio app

      A través del servicio app se configurará un contenedor llamado travellist-app. Crea una nueva imagen de Docker basada en un Dockerfile ubicado en la misma ruta que el archivo docker-compose.yml. La nueva imagen se guardará a nivel local con el nombre travellist.

      Aunque el root de documentos que se proporciona como la aplicación se encuentra en el contenedor nginx, también necesitamos los archivos de la aplicación en algún lugar dentro del contenedor app para poder ejecutar tareas de línea de comandos con la herramienta Laravel Artisan.

      Copie la siguiente definición de servicio en su nodo services, dentro del archivo docker-compose.yml:

      docker-compose.yml

        app:
          build:
            args:
              user: sammy
              uid: 1000
            context: ./
            dockerfile: Dockerfile
          image: travellist
          container_name: travellist-app
          restart: unless-stopped
          working_dir: /var/www/
          volumes:
            - ./:/var/www
          networks:
            - travellist
      

      Estas configuraciones tienen los siguientes atributos:

      • build: en esta configuración indica a Docker Compose que cree una imagen local para el servicio app, y usa la ruta especificada (context) y Dockerfile para las instrucciones. Los argumentos user y uid se insertan en Dockerfile para personalizar los comandos de creación del usuario en el tiempo de compilación.
      • image: nombre que se usará para la imagen que se creará.
      • container_name: configura el nombre del contenedor para este servicio.
      • restart: siempre ejecuta un reinicio, a menos que se detenga el servicio.
      • working_dir: establece el directorio predeterminado para este servicio como /var/www.
      • volumes: crea un volumen compartido en el que se sincronizarán los contenidos del directorio actual con /var/www dentro del contenedor. Tenga en cuenta que esto no es su root de documentos, ya que este residirá en el contenedor nginx.
      • networks: configura este servicio para que se utilice una red llamada travellist.

      El servicio db

      En el servicio db se utiliza una imagen previamente creada de MySQL 5.7 de Docker Hub. Debido a que en Docker Compose se cargan automáticamente los archivos de variable .env ubicados en el mismo directorio que el archivo docker-compose.yml, podemos obtener la configuración de nuestra base de datos del archivo Laravel .env que creamos en un paso anterior.

      Incluya la siguiente definición de servicio en el nodo services, justo después del servicio app:

      docker-compose.yml

        db:
          image: mysql:5.7
          container_name: travellist-db
          restart: unless-stopped
          environment:
            MYSQL_DATABASE: ${DB_DATABASE}
            MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
            MYSQL_PASSWORD: ${DB_PASSWORD}
            MYSQL_USER: ${DB_USERNAME}
            SERVICE_TAGS: dev
            SERVICE_NAME: mysql
          volumes:
            - ./docker-compose/mysql:/docker-entrypoint-initdb.d
          networks:
            - travellist
      

      Estas configuraciones hacen lo siguiente:

      • image: define la imagen de Docker que debe utilizarse para este contenedor. En este caso, usamos una imagen MySQL 5.7 de Docker Hub.
      • container_name: establece el nombre del contenedor para el servicio travellist-db.
      • restart: reinicie siempre este servicio, a menos que se detenga de forma explicita.
      • environment: define las variables de entorno en el nuevo contenedor. Usaremos valores obtenidos del archivo Laravel .env para establecer nuestro servicio de MySQL, que creará automáticamente una nueva base de datos y usuario basadas en las variables de entorno proporcionadas.
      • volumes: crea un volumen para compartir un volcado de base de datos .sql que se usará para inicializar la base de datos de la aplicación. En la imagen de MySQL se importarán automáticamente archivos .sql ubicados en el directorio /docker-entrypoint-initdb.d dentro del contenedor.
      • networks: configura este servicio para que se utilice una red llamada travellist.

      El servicio nginx

      En el servicio nginx se utiliza una imagen previamente creada de Nginx en la parte superior de Alpine, una distribución ligera de Linux. Se crea un contenedor llamado travellist-nginx y se utiliza la definición ports para crear un redireccionamiento del puerto 8000 en el sistema host al puerto 80 dentro del contenedor.

      Incluya la siguiente definición de servicio en su nodo services, justo después del servicio db:

      docker-compose.yml

        nginx:
          image: nginx:1.17-alpine
          container_name: travellist-nginx
          restart: unless-stopped
          ports:
            - 8000:80
          volumes:
            - ./:/var/www
            - ./docker-compose/nginx:/etc/nginx/conf.d
          networks:
            - travellist
      

      Esta configuración hace lo siguiente:

      • image: define la imagen de Docker que debe utilizarse para este contenedor. En este caso, usaremos la imagen Alpine Nginx 1.17.
      • container_name: establece el nombre del contenedor para el servicio travellist-nginx.
      • restart: reinicie siempre este servicio, a menos que se detenga de forma explicita.
      • ports: establece un redireccionamiento de puerto que permitirá el acceso externo a través del puerto 8000 al servidor web que se ejecuta en el puerto 80 dentro del contenedor.
      • volumes: crea dos volúmenes compartidos. El primero sincronizará los contenidos del directorio actual con /var/www dentro del contenedor. De esta manera, cuando realice cambios locales en los archivos de la aplicación, se reflejarán rápidamente en la aplicación proporcionada por Nginx dentro del contenedor. En el segundo volumen, se asegurará que nuestro archivo de configuración de Nginx, ubicado en docker-compose/nginx/travellist.conf, se copie a la carpeta de configuración de Nginx del contenedor.
      • networks: configura este servicio para que se utilice una red llamada travellist.

      Archivo docker-compose.yml terminado

      Este es el aspecto de nuestro archivo docker-compose.yml terminado:

      docker-compose.yml

      version: "3.7"
      services:
        app:
          build:
            args:
              user: sammy
              uid: 1000
            context: ./
            dockerfile: Dockerfile
          image: travellist
          container_name: travellist-app
          restart: unless-stopped
          working_dir: /var/www/
          volumes:
            - ./:/var/www
          networks:
            - travellist
      
        db:
          image: mysql:5.7
          container_name: travellist-db
          restart: unless-stopped
          environment:
            MYSQL_DATABASE: ${DB_DATABASE}
            MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
            MYSQL_PASSWORD: ${DB_PASSWORD}
            MYSQL_USER: ${DB_USERNAME}
            SERVICE_TAGS: dev
            SERVICE_NAME: mysql
          volumes:
            - ./docker-compose/mysql:/docker-entrypoint-initdb.d
          networks:
            - travellist
      
        nginx:
          image: nginx:alpine
          container_name: travellist-nginx
          restart: unless-stopped
          ports:
            - 8000:80
          volumes:
            - ./:/var/www
            - ./docker-compose/nginx:/etc/nginx/conf.d/
          networks:
            - travellist
      
      networks:
        travellist:
          driver: bridge
      

      Asegúrese de guardar el archivo cuando termine.

      Paso 6: Ejecutar la aplicación con Docker Compose

      Ahora, usaremos comandos docker-compose para crear la imagen de la aplicación y ejecutar los servicios que especificamos en nuestra configuración.

      Cree la imagen app con el siguiente comando:

      La aplicación de este comando puede tardar unos minutos en completarse. Verá un resultado similar a este:

      Output

      Building app Step 1/11 : FROM php:7.4-fpm ---> fa37bd6db22a Step 2/11 : ARG user ---> Running in f71eb33b7459 Removing intermediate container f71eb33b7459 ---> 533c30216f34 Step 3/11 : ARG uid ---> Running in 60d2d2a84cda Removing intermediate container 60d2d2a84cda ---> 497fbf904605 Step 4/11 : RUN apt-get update && apt-get install -y git curl libpng-dev libonig-dev ... Step 7/11 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer ---> e499f74896e3 Step 8/11 : RUN useradd -G www-data,root -u $uid -d /home/$user $user ---> Running in 232ef9c7dbd1 Removing intermediate container 232ef9c7dbd1 ---> 870fa3220ffa Step 9/11 : RUN mkdir -p /home/$user/.composer && chown -R $user:$user /home/$user ---> Running in 7ca8c0cb7f09 Removing intermediate container 7ca8c0cb7f09 ---> 3d2ef9519a8e Step 10/11 : WORKDIR /var/www ---> Running in 4a964f91edfa Removing intermediate container 4a964f91edfa ---> 00ada639da21 Step 11/11 : USER $user ---> Running in 9f8e874fede9 Removing intermediate container 9f8e874fede9 ---> fe176ff4702b Successfully built fe176ff4702b Successfully tagged travellist:latest

      Cuando se complete la compilación, podrá ejecutar el entorno en el modo de segundo plano con lo siguiente:

      Output

      Creating travellist-db ... done Creating travellist-app ... done Creating travellist-nginx ... done

      Con esto, se ejecutarán sus contenedores en segundo plano. Para mostrar información sobre el estado de sus servicios activos, ejecute lo siguiente:

      Verá resultados como este:

      Output

      Name Command State Ports ------------------------------------------------------------------------------- travellist-app docker-php-entrypoint php-fpm Up 9000/tcp travellist-db docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp travellist-nginx nginx -g daemon off; Up 0.0.0.0:8000->80/tcp

      Su entorno ahora estárá configurado y en funcionamiento, pero aún debemos ejecutar algunos comandos para finalizar la configuración de la aplicación. Puede usar el comando docker-compose exec para ejecutar comandos en los contenedores de servicios, como ls -l. Este muestra información detallada sobre los archivos en el directorio de la aplicación:

      • docker-compose exec app ls -l

      Output

      total 256 -rw-rw-r-- 1 sammy 1001 738 Jan 15 16:46 Dockerfile -rw-rw-r-- 1 sammy 1001 101 Jan 7 08:05 README.md drwxrwxr-x 6 sammy 1001 4096 Jan 7 08:05 app -rwxr-xr-x 1 sammy 1001 1686 Jan 7 08:05 artisan drwxrwxr-x 3 sammy 1001 4096 Jan 7 08:05 bootstrap -rw-rw-r-- 1 sammy 1001 1501 Jan 7 08:05 composer.json -rw-rw-r-- 1 sammy 1001 179071 Jan 7 08:05 composer.lock drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 config drwxrwxr-x 5 sammy 1001 4096 Jan 7 08:05 database drwxrwxr-x 4 sammy 1001 4096 Jan 15 16:46 docker-compose -rw-rw-r-- 1 sammy 1001 1015 Jan 15 16:45 docker-compose.yml -rw-rw-r-- 1 sammy 1001 1013 Jan 7 08:05 package.json -rw-rw-r-- 1 sammy 1001 1405 Jan 7 08:05 phpunit.xml drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 public -rw-rw-r-- 1 sammy 1001 273 Jan 7 08:05 readme.md drwxrwxr-x 6 sammy 1001 4096 Jan 7 08:05 resources drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 routes -rw-rw-r-- 1 sammy 1001 563 Jan 7 08:05 server.php drwxrwxr-x 5 sammy 1001 4096 Jan 7 08:05 storage drwxrwxr-x 4 sammy 1001 4096 Jan 7 08:05 tests -rw-rw-r-- 1 sammy 1001 538 Jan 7 08:05 webpack.mix.js

      Ahora, ejecutaremos composer install para instalar las dependencias de la aplicación:

      • docker-compose exec app composer install

      Verá resultados como este:

      Output

      Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals - Installing doctrine/inflector (1.3.1): Downloading (100%) - Installing doctrine/lexer (1.2.0): Downloading (100%) - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%) - Installing erusev/parsedown (1.7.4): Downloading (100%) - Installing symfony/polyfill-ctype (v1.13.1): Downloading (100%) - Installing phpoption/phpoption (1.7.2): Downloading (100%) - Installing vlucas/phpdotenv (v3.6.0): Downloading (100%) - Installing symfony/css-selector (v5.0.2): Downloading (100%) … Generating optimized autoload files > IlluminateFoundationComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: facade/ignition Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully.

      Lo último que debemos hacer antes de probar la aplicación es generar una clave de aplicación única con la herramienta de línea de comandos de Laravel artisan. Esta clave se utiliza para cifrar las sesiones de los usuarios y otros datos confidenciales:

      • docker-compose exec app php artisan key:generate

      Output

      Application key set successfully.

      Ahora diríjase a su navegador y acceda al nombre de dominio o dirección IP de su servidor en el puerto 8000:

      http://server_domain_or_IP:8000
      

      Verá una página como la siguiente:

      Aplicación de demostración de Laravel

      Puede usar el comando logs para verificar los registros generados por sus servicios:

      • docker-compose logs nginx
      Attaching to travellist-nginx
      travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:25 +0000] "GET / HTTP/1.1" 200 626 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
      travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:26 +0000] "GET /favicon.ico HTTP/1.1" 200 0 "http://localhost:8000/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
      travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:42 +0000] "GET / HTTP/1.1" 200 626 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
      …
      

      Si desea pausar su entorno de Docker Compose mientras mantiene el estado de todos sus servicios, ejecute lo siguiente:

      Output

      Pausing travellist-db ... done Pausing travellist-nginx ... done Pausing travellist-app ... done

      Luego podrá reanudar sus servicios con lo siguiente:

      Output

      Unpausing travellist-app ... done Unpausing travellist-nginx ... done Unpausing travellist-db ... done

      Para cerrar su entorno de Docker Compose y eliminar por completo sus contenedores, redes y volúmenes, ejecute lo siguiente:

      Output

      Stopping travellist-nginx ... done Stopping travellist-db ... done Stopping travellist-app ... done Removing travellist-nginx ... done Removing travellist-db ... done Removing travellist-app ... done Removing network travellist-laravel-demo_travellist

      Para acceder a una visión general de todos los comandos de Docker Compose, consulte la referencia de línea de comandos de Docker Compose.

      Conclusión

      A lo largo de esta guía, configuramos un entorno de Docker con tres contenedores usando Docker Compose para definir nuestra infraestructura en un archivo YAML.

      A partir de este punto, puede trabajar en su aplicación de Laravel sin necesidad de instalar y configurar un servidor web local para el desarrollo y las pruebas. Además, trabajará con un entorno disponible que se puede replicar y distribuir de forma sencilla, lo cual puede resultarle útil al desarrollar su aplicación y realizar la transición a un entorno de producción.



      Source link