One place for hosting & domains

      Docker

      Cómo crear una aplicación Node.js con Docker


      Introducción

      La plataforma Docker permite a los desarrolladores empaquetar y ejecutar aplicaciones como contenedores. Un contenedor es un proceso aislado que se ejecuta en un sistema operativo compartido, ofreciendo una alternativa más ligera para máquinas virtuales. Si bien los contenedores no son nuevos, ofrecen beneficios, como aislamiento de procesos y estandarización de entornos, que están creciendo en importancia a medida que más desarrolladores utilizan arquitecturas de aplicaciones distribuidas.

      Cuando se construye y escala una aplicación con Docker, el punto de partida suele ser la creación de una imagen para su aplicación, que, luego, puede ejecutar en un contenedor. La imagen incluye el código, las bibliotecas, los archivos de configuración, las variables del entorno y el tiempo de ejecución de su aplicación. Usar una imagen asegura que el entorno de su contenedor esté estandarizado y que solo contenga lo necesario para crear y ejecutar su aplicación.

      En este tutorial, creará la imagen de una aplicación para un sitio web estático que utiliza el marco de trabajo Express y Bootstrap. Luego, creará un contenedor usando esa imagen y la insertará en Docker Hub para su uso futuro. Por último, extraerá la imagen almacenada de su repositorio de Docker Hub y creará otro contenedor para demostrar cómo puede recrear y escalar su aplicación.

      Requisitos previos

      Para seguir este tutorial, necesitará lo siguiente:

      Paso 1: instalación de las dependencias de su aplicación

      Para crear su imagen, primero, deberá crear los archivos de su aplicación, que, luego, puede copiar a su contenedor. Estos archivos incluirán el contenido estático, el código y las dependencias de su aplicación.

      Primero, cree un directorio para su proyecto en el directorio principal de su usuario no root. Llamaremos al nuestro node_project, pero no es necesario que usted utilice la misma denominación:

      Navegue a este directorio:

      Este será el directorio root del proyecto.

      A continuación, cree un archivo package.json con las dependencias de su proyecto y otra información de identificación. Abra el archivo con nano o su editor favorito:

      Añada la siguiente información sobre el proyecto, incluido su nombre, autor, licencia, punto de entrada y dependencias. Asegúrese de sustituir la información de autor con su propio nombre y sus detalles de contacto:

      ~/node_project/package.json

      {
        "name": "nodejs-image-demo",
        "version": "1.0.0",
        "description": "nodejs image demo",
        "author": "Sammy the Shark <sammy@example.com>",
        "license": "MIT",
        "main": "app.js",
        "keywords": [
          "nodejs",
          "bootstrap",
          "express"
        ],
        "dependencies": {
          "express": "^4.16.4"
        }
      }
      

      Este archivo incluye el nombre, el autor y la licencia del proyecto con los que se comparte. Npm recomienda que el nombre de su proyecto sea corto y descriptivo, así como evitar duplicaciones en el registro de npm. Hemos incluido la licencia MIT en el campo de licencia, lo que permite el uso y la distribución gratuitos del código de la aplicación.

      Además, el archivo especifica lo siguiente:

      • "main": el punto de entrada de la aplicación, app.js. Creará este archivo a continuación.
      • "dependencies": las dependencias del proyecto; en este caso, Express 4.16.4 o superior.

      Aunque este archivo no enumera un repositorio, puede añadir uno al seguir estas pautas sobre la adición de un repositorio a su archivo package.json. Es una buena adición si va a crear versiones de su aplicación.

      Guarde y cierre el archivo cuando haya terminado de realizar cambios.

      Para instalar las dependencias de su proyecto, ejecute el siguiente comando:

      Esto instalará los paquetes que haya incluido en su archivo package.json en el directorio de su proyecto.

      Ahora, podemos proceder a crear los archivos de la aplicación.

      Paso 2: creación de los archivos de la aplicación

      Crearemos una página web que ofrece información a los usuarios sobre los tiburones. Nuestra aplicación tendrá un punto de entrada principal, app.js y un directorio views que incluirá los activos estáticos del proyecto. La página de inicio, index.html, ofrecerá a los usuarios algunos datos preliminares y un enlace a una página con información más detallada sobre tiburones, sharks.html. En el directorio views, crearemos tanto la página de inicio como la página sharks.html.

      Primero, abra el archivo app.js en el directorio principal del proyecto para definir las rutas del proyecto:

      La primera parte del archivo creará la aplicación Express y los objetos Router, y definirá el directorio base y el puerto como constantes:

      ~/node_project/app.js

      const express = require('express');
      const app = express();
      const router = express.Router();
      
      const path = __dirname + '/views/';
      const port = 8080;
      

      La función require carga el módulo express, que, luego, usaremos para crear los objetos app y router. El objeto router realizará la función de enrutamiento de la aplicación, y, al definir las rutas de método HTTP, las añadiremos a este objeto para definir cómo se deben manejar las solicitudes.

      Esta sección del archivo también establece dos constantes: path y port:

      • path: define el directorio base, que será el subdirectorio de views dentro del directorio actual del proyecto.
      • port: le indica a la aplicación que escuche el puerto 8080 y se conecte a él.

      A continuación, establezca las rutas de la aplicación usando el objeto router:

      ~/node_project/app.js

      ...
      
      router.use(function (req,res,next) {
        console.log("https://www.digitalocean.com/" + req.method);
        next();
      });
      
      router.get("https://www.digitalocean.com/", function(req,res){
        res.sendFile(path + 'index.html');
      });
      
      router.get("https://www.digitalocean.com/sharks", function(req,res){
        res.sendFile(path + 'sharks.html');
      });
      

      La función router.use carga una función de middleware que registrará las solicitudes del router y las transmitirá a las rutas de la aplicación. Estas se definen en las funciones siguientes, que especifican que una solicitud GET a la URL del proyecto base debe devolver la página index.html, mientras que una solicitud GET a la ruta /sharks debe devolver sharks.html.

      Por último, monte el middleware router y los activos estáticos de la aplicación e indíquele a esta que escuche por el puerto 8080:

      ~/node_project/app.js

      ...
      
      app.use(express.static(path));
      app.use("https://www.digitalocean.com/", router);
      
      app.listen(port, function () {
        console.log('Example app listening on port 8080!')
      })
      

      El archivo app.js terminado tendrá este aspecto:

      ~/node_project/app.js

      const express = require('express');
      const app = express();
      const router = express.Router();
      
      const path = __dirname + '/views/';
      const port = 8080;
      
      router.use(function (req,res,next) {
        console.log("https://www.digitalocean.com/" + req.method);
        next();
      });
      
      router.get("https://www.digitalocean.com/", function(req,res){
        res.sendFile(path + 'index.html');
      });
      
      router.get("https://www.digitalocean.com/sharks", function(req,res){
        res.sendFile(path + 'sharks.html');
      });
      
      app.use(express.static(path));
      app.use("https://www.digitalocean.com/", router);
      
      app.listen(port, function () {
        console.log('Example app listening on port 8080!')
      })
      

      Guarde y cierre el archivo cuando haya terminado.

      A continuación, añadamos algunos contenidos estáticos a la aplicación. Comience por crear el directorio views:

      Abra el archivo de la página de destino, index.html:

      Añada el siguiente código al archivo, que importará Bootstrap y creará un componente jumbotron con un enlace a la página de información más detallada sharks.html:

      ~/node_project/views/index.html

      <!DOCTYPE html>
      <html lang="en">
      
      <head>
          <title>About Sharks</title>
          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
          <link href="https://www.digitalocean.com/css/styles.css" rel="stylesheet">
          <link href="https://fonts.googleapis.com/css?family=Merriweather:400,700" rel="stylesheet" type="text/css">
      </head>
      
      <body>
          <nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md">
              <div class="container">
                  <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span>
                  </button> <a class="navbar-brand" href="https://www.digitalocean.com/#">Everything Sharks</a>
                  <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                      <ul class="nav navbar-nav mr-auto">
                          <li class="active nav-item"><a href="https://www.digitalocean.com/" class="nav-link">Home</a>
                          </li>
                          <li class="nav-item"><a href="https://www.digitalocean.com/sharks" class="nav-link">Sharks</a>
                          </li>
                      </ul>
                  </div>
              </div>
          </nav>
          <div class="jumbotron">
              <div class="container">
                  <h1>Want to Learn About Sharks?</h1>
                  <p>Are you ready to learn about sharks?</p>
                  <br>
                  <p><a class="btn btn-primary btn-lg" href="https://www.digitalocean.com/sharks" role="button">Get Shark Info</a>
                  </p>
              </div>
          </div>
          <div class="container">
              <div class="row">
                  <div class="col-lg-6">
                      <h3>Not all sharks are alike</h3>
                      <p>Though some are dangerous, sharks generally do not attack humans. Out of the 500 species known to researchers, only 30 have been known to attack humans.
                      </p>
                  </div>
                  <div class="col-lg-6">
                      <h3>Sharks are ancient</h3>
                      <p>There is evidence to suggest that sharks lived up to 400 million years ago.
                      </p>
                  </div>
              </div>
          </div>
      </body>
      
      </html>
      

      Aquí, la barra de navegación de nivel superior permite a los usuarios alternar entre las páginas Home y Sharks. En el subcomponente navbar-nav, estamos usando la clase active de Bootstrap para indicar la página actual al usuario. También especificamos las rutas a nuestras páginas estáticas, que coinciden con las rutas que definimos en app.js:

      ~/node_project/views/index.html

      ...
      <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
         <ul class="nav navbar-nav mr-auto">
            <li class="active nav-item"><a href="https://www.digitalocean.com/" class="nav-link">Home</a>
            </li>
            <li class="nav-item"><a href="https://www.digitalocean.com/sharks" class="nav-link">Sharks</a>
            </li>
         </ul>
      </div>
      ...
      

      Además, creamos un enlace a nuestra página de información de tiburones en el botón de jumbotron:

      ~/node_project/views/index.html

      ...
      <div class="jumbotron">
         <div class="container">
            <h1>Want to Learn About Sharks?</h1>
            <p>Are you ready to learn about sharks?</p>
            <br>
            <p><a class="btn btn-primary btn-lg" href="https://www.digitalocean.com/sharks" role="button">Get Shark Info</a>
            </p>
         </div>
      </div>
      ...
      

      También hay un enlace a una hoja de estilo personalizado en el encabezado:

      ~/node_project/views/index.html

      ...
      <link href="https://www.digitalocean.com/css/styles.css" rel="stylesheet">
      ...
      

      Crearemos esta hoja de estilo al final de este paso.

      Guarde y cierre el archivo cuando haya terminado.

      Con la página de destino de la aplicación establecida, podemos crear nuestra página de información de tiburones, sharks.html, que ofrecerá más información a los usuarios interesados en los tiburones.

      Abra el archivo:

      Añada el siguiente código, que importa Bootstrap y la hoja de estilo personalizado, y ofrece a los usuarios información detallada sobre ciertos tiburones:

      ~/node_project/views/sharks.html

      <!DOCTYPE html>
      <html lang="en">
      
      <head>
          <title>About Sharks</title>
          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
          <link href="https://www.digitalocean.com/css/styles.css" rel="stylesheet">
          <link href="https://fonts.googleapis.com/css?family=Merriweather:400,700" rel="stylesheet" type="text/css">
      </head>
      <nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md">
          <div class="container">
              <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span>
              </button> <a class="navbar-brand" href="https://www.digitalocean.com/">Everything Sharks</a>
              <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                  <ul class="nav navbar-nav mr-auto">
                      <li class="nav-item"><a href="https://www.digitalocean.com/" class="nav-link">Home</a>
                      </li>
                      <li class="active nav-item"><a href="https://www.digitalocean.com/sharks" class="nav-link">Sharks</a>
                      </li>
                  </ul>
              </div>
          </div>
      </nav>
      <div class="jumbotron text-center">
          <h1>Shark Info</h1>
      </div>
      <div class="container">
          <div class="row">
              <div class="col-lg-6">
                  <p>
                      <div class="caption">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.
                      </div>
                      <img src="https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg" alt="Sawshark">
                  </p>
              </div>
              <div class="col-lg-6">
                  <p>
                      <div class="caption">Other sharks are known to be friendly and welcoming!</div>
                      <img src="https://assets.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">
                  </p>
              </div>
          </div>
      </div>
      
      </html>
      

      Tenga en cuenta que, en este archivo, volvemos a usar la clase active para indicar la página actual.

      Guarde y cierre el archivo cuando haya terminado.

      Por último, cree la hoja de estilo CSS personalizado a la que se vinculó en index.html y sharks.html creando, primero, una carpeta css en el directorio views:

      Abra la hoja de estilo:

      • nano views/css/styles.css

      Añada el siguiente código, que establecerá el color y la fuente deseados para nuestras páginas:

      ~/node_project/views/css/styles.css

      .navbar {
          margin-bottom: 0;
      }
      
      body {
          background: #020A1B;
          color: #ffffff;
          font-family: 'Merriweather', sans-serif;
      }
      
      h1,
      h2 {
          font-weight: bold;
      }
      
      p {
          font-size: 16px;
          color: #ffffff;
      }
      
      .jumbotron {
          background: #0048CD;
          color: white;
          text-align: center;
      }
      
      .jumbotron p {
          color: white;
          font-size: 26px;
      }
      
      .btn-primary {
          color: #fff;
          text-color: #000000;
          border-color: white;
          margin-bottom: 5px;
      }
      
      img,
      video,
      audio {
          margin-top: 20px;
          max-width: 80%;
      }
      
      div.caption: {
          float: left;
          clear: both;
      }
      

      Además de establecer fuentes y color, este archivo también limita el tamaño de las imágenes al especificar un ancho máximo, max-width, del 80%. Esto impedirá que ocupen más espacio del que quisiéramos en la página.

      Guarde y cierre el archivo cuando haya terminado.

      Con los archivos de la aplicación establecidos y las dependencias del proyecto instaladas, está listo para iniciar la aplicación.

      Si siguió el tutorial de configuración inicial del servidor que se indica en los requisitos previos, tendrá un firewall activo que solo permite tráfico SSH. Para permitir el tráfico al puerto 8080 ejecute lo siguiente:

      Para iniciar la aplicación, asegúrese de estar en el directorio root de su proyecto:

      Inicie la aplicación con node app.js:

      Ingrese la dirección http://your_server_ip:8080 en su navegador. Visualizará la siguiente página de destino:

      Página de destino de la aplicación

      Haga clic en el botón Get Shark Info. Visualizará la siguiente página de información:

      Página de información de tiburones

      Ahora, tiene una aplicación lista y en funcionamiento. Cuando esté listo, salga del servidor al pulsar CTRL+C. Ahora, podemos pasar a crear el Dockerfile que nos permitirá recrear y escalar esta aplicación como deseemos.

      Paso 3: escribir el Dockerfile

      Su Dockerfile especifica qué se incluirá en el contenedor de su aplicación cuando se ejecute. 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 pautas sobre la creación de contenedores optimizados, haremos que nuestra imagen sea tan eficiente como sea posible al minimizar el número de capas de imagen y restringir la función de la imagen a un único propósito: recrear los archivos y el contenido estático de nuestra aplicación.

      En el directorio root de su proyecto, cree el Dockerfile:

      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 base para nuestra aplicación, que formará el punto de partida de la creación de la aplicación.

      Procederemos a utilizar la imagen node:10-alpine, dado que, al momento de redactar este artículo, es la versión LTS de Node.js recomendada. 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 la imagen Node de Docker Hub.

      Añada la siguiente instrucción FROM para configurar la imagen base de la aplicación:

      ~/node_project/Dockerfile

      FROM node:10-alpine
      

      Esta imagen incluye Node.js y npm. Cada Dockerfile debe comenzar con una instrucción FROM.

      De forma predeterminada, la imagen Node de Docker incluye un usuario node no root que puede usar para evitar ejecutar el contenedor de su aplicación como root. Evitar ejecutar contenedores como root y restringir las capacidades del contenedor solo a las necesarias para la ejecución de sus procesos es una práctica de seguridad recomendada. Por lo tanto, utilizaremos el directorio principal del usuario node como directorio de trabajo de nuestra aplicación, y procederemos a configurarlo como nuestro usuario dentro del contenedor. Para obtener más información sobre las mejores prácticas al trabajar con la imagen Node de Docker, consulte esta guía de prácticas recomendadas.

      Para ajustar los permisos en el código de nuestra aplicación en el contenedor, cree el subdirectorio node_modules en /home/node y el directorio app. Crear estos directorios garantizará que tengan los permisos deseados, lo que será importante al crear módulos de nodo locales en el contenedor con npm install. Además de crear estos directorios, estableceremos la propiedad sobre ellos a nuestro usuario node:

      ~/node_project/Dockerfile

      ...
      RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
      

      Para obtener más información sobre la utilidad de consolidar instrucciones RUN, consulte esta discusión sobre cómo gestionar capas de contenedores.

      A continuación, establezca el directorio de trabajo de la aplicación en /home/node/app:

      ~/node_project/Dockerfile

      ...
      WORKDIR /home/node/app
      

      Si no hay un WORKDIR establecido, Docker creará uno por defecto, por lo que es buena idea configurarlo de manera explícita.

      A continuación, copie los archivos package.json y package-lock.json (para npm 5+):

      ~/node_project/Dockerfile

      ...
      COPY package*.json ./
      

      Añadir esta instrucción COPY antes de ejecutar npm install o copiar el código de la aplicación nos permite aprovechar el mecanismo de almacenamiento en caché de Docker. En cada etapa de la creación, Docker comprobará si tiene una capa en caché para esa instrucción en particular. Si cambiamos package.json, esta capa se reconstruye, pero si no lo hacemos, esta instrucción le permitirá a Docker utilizar la capa de imagen existente y omitir la reinstalación de nuestros módulos de nodo.

      Para garantizar que todos los archivos de la aplicación sean propiedad del usuario node no root, incluido el contenido del directorio node_modules, cambie el usuario a node antes de ejecutar npm install:

      ~/node_project/Dockerfile

      ...
      USER node
      

      Tras copiar las dependencias del proyecto y cambiar nuestro usuario, podemos ejecutar npm install:

      ~/node_project/Dockerfile

      ...
      RUN npm install
      

      A continuación, copie el código de su aplicación con los permisos apropiados al directorio de la aplicación en el contenedor:

      ~/node_project/Dockerfile

      ...
      COPY --chown=node:node . .
      

      Esto garantizará que los archivos de la aplicación sean propiedad del usuario node no root.

      Por último, exponga el puerto 8080 en el contenedor e inicie la aplicación:

      ~/node_project/Dockerfile

      ...
      EXPOSE 8080
      
      CMD [ "node", "app.js" ]
      

      EXPOSE no publica el puerto, sino que actúa como una manera de documentar qué puertos del contenedor se publicarán en el tiempo de ejecución. CMD ejecuta el comando para iniciar la aplicación; en este caso, node app.js. Tenga en cuenta que debe haber una sola instrucción CMD en cada Dockerfile. Si incluye más de una, solo la última tendrá efecto.

      Se pueden hacer muchas cosas con Dockerfile. Para obtener una lista completa de instrucciones, consulte la documentación de referencia de Dockerfile de Docker.

      Así es como se ve el Dockerfile completo:

      ~/node_project/Dockerfile

      
      FROM node:10-alpine
      
      RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
      
      WORKDIR /home/node/app
      
      COPY package*.json ./
      
      USER node
      
      RUN npm install
      
      COPY --chown=node:node . .
      
      EXPOSE 8080
      
      CMD [ "node", "app.js" ]
      

      Guarde y cierre el archivo cuando haya terminado de editar.

      Antes de crear la imagen de la aplicación, añadamos un archivo .dockerignore. Con un funcionamiento similar al de un archivo.gitignore, .dockerignore especifica qué archivos y directorios del directorio de su proyecto no deben copiarse a su contenedor.

      Abra el archivo .dockerignore:

      Dentro del archivo, añada sus módulos de nodo locales, registros de npm, Dockerfile y el archivo .dockerignore:

      ~/node_project/.dockerignore

      node_modules
      npm-debug.log
      Dockerfile
      .dockerignore
      

      Si está trabajando con Git, también es conveniente que añada su directorio .git y el archivo .gitignore.

      Guarde y cierre el archivo cuando haya terminado.

      Ahora, está listo para crear la imagen de la aplicación usando el comando docker build. Usar la marca -t con docker build le permitirá etiquetar la imagen con un nombre fácil de recordar. Dado que vamos a insertar la imagen en Docker Hub, incluiremos nuestro nombre de usuario de Docker Hub en la etiqueta. Vamos a etiquetar la imagen como nodejs-image-demo, pero puede utilizar un nombre de su elección. Recuerde reemplazar también your_dockerhub_usernamecon su nombre de usuario de Docker Hub:

      • docker build -t your_dockerhub_username/nodejs-image-demo .

      El . especifica que el contexto de compilación es el directorio actual.

      La compilación de la imagen tomará entre uno y dos minutos. Una vez que se haya completado, verifique sus imágenes:

      Verá la salida siguiente:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 8 seconds ago 73MB node 10-alpine f09e7c96b6de 3 weeks ago 70.7MB

      Ahora, es posible crear un contenedor con esta imagen usandodocker run. Incluiremos tres marcas con este comando:

      • -p: edita el puerto en el contenedor y lo asigna a un puerto en nuestro host. Usaremos el puerto 80 en el host, pero puede modificarlo como considere necesario si tiene otro proceso en ejecución en ese puerto. Para obtener más información sobre cómo funciona, consulte esta discusión en la documentación de Docker sobre ](https://docs.docker.com/v17.09/engine/userguide/networking/default_network/binding/)enlaces de puerto[.
      • -d: ejecuta el contenedor en segundo plano.
      • --name: permite darle al contenedor un nombre fácil de recordar.

      Ejecute el siguiente comando para compilar el contenedor:

      • docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo

      Una vez que su contenedor esté listo y en funcionamiento, puede inspeccionar una lista de sus contenedores en ejecución con docker ps:

      Verá la salida siguiente:

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e50ad27074a7 your_dockerhub_username/nodejs-image-demo "node app.js" 8 seconds ago Up 7 seconds 0.0.0.0:80->8080/tcp nodejs-image-demo

      Con el contenedor en ejecución, ahora, puede visitar su aplicación ingresando la dirección http://your_server_ip en su navegador. Visualizará la página de inicio de su aplicación una vez más:

      Página de destino de la aplicación

      Ahora que creó una imagen para su aplicación, puede insertarla en Docker Hub para su uso futuro.

      Paso 4: utilizar un repositorio para trabajar con imágenes

      Al insertar la imagen de su aplicación en un registro como Docker Hub, la pone a disposición para su uso posterior a medida que construye y escala sus contenedores. Demostraremos cómo funciona esto al insertar la imagen de la aplicación en un repositorio y, luego, usar la imagen para recrear nuestro contenedor.

      El primer paso para insertar la imagen es ingresar a la cuenta de Docker Hub que creó en los requisitos previos:

      • docker login -u your_dockerhub_username

      Cuando se le indique, ingrese la contraseña de la cuenta de Docker Hub. Iniciar sesión de esta manera creará un archivo ~/.docker/config.json en el directorio principal de su usuario con sus credenciales de Docker Hub.

      Ahora, puede insertar la imagen de la aplicación en Docker Hub usando la etiqueta que creó anteriormente, your_dockerhub_username/nodejs-image-demo:

      • docker push your_dockerhub_username/nodejs-image-demo

      Vamos a probar la utilidad del registro de imágenes al destruir el contenedor y la imagen de nuestra aplicación actual y volver a compilarlos con la imagen en nuestro repositorio.

      Primero, enumere sus contenedores en ejecución:

      Verá la salida siguiente:

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e50ad27074a7 your_dockerhub_username/nodejs-image-demo "node app.js" 3 minutes ago Up 3 minutes 0.0.0.0:80->8080/tcp nodejs-image-demo

      Mediante CONTAINER ID, enumerada en su salida, detenga la ejecución del contenedor de la aplicación. Asegúrese de sustituir la ID resaltada debajo por su propia CONTAINER ID:

      Enumere todas sus imágenes con la marca -a:

      Visualizará la siguiente salida con el nombre de su imagen,your_dockerhub_username/nodejs-image-demo, junto con la imagen node y las demás imágenes de su compilación:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 7 minutes ago 73MB <none> <none> 2e3267d9ac02 4 minutes ago 72.9MB <none> <none> 8352b41730b9 4 minutes ago 73MB <none> <none> 5d58b92823cb 4 minutes ago 73MB <none> <none> 3f1e35d7062a 4 minutes ago 73MB <none> <none> 02176311e4d0 4 minutes ago 73MB <none> <none> 8e84b33edcda 4 minutes ago 70.7MB <none> <none> 6a5ed70f86f2 4 minutes ago 70.7MB <none> <none> 776b2637d3c1 4 minutes ago 70.7MB node 10-alpine f09e7c96b6de 3 weeks ago 70.7MB

      Elimine el contenedor detenido y todas las imágenes, incluso las no utilizadas o pendientes, con el siguiente comando:

      Escriba y cuando se le indique, en la salida, para confirmar que desea eliminar el contenedor detenido y las imágenes. Tenga en cuenta que esto también eliminará la memoria caché de su compilación.

      Ahora, eliminó tanto la imagen de su aplicación como el contenedor que la ejecutaba. Para obtener más información sobre la eliminación de contenedores, imágenes y volúmenes de Docker, consulte la sección Cómo eliminar imágenes, contenedores y volúmenes de Docker.

      Con todas sus imágenes y contenedores eliminados, ahora, puede extraer la imagen de la aplicación de Docker Hub:

      • docker pull your_dockerhub_username/nodejs-image-demo

      Enumere sus imágenes una vez más:

      Visualizará la imagen de su aplicación:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 11 minutes ago 73MB

      Ahora, puede volver a compilar su contenedor usando el comando que se indica en el Paso 3:

      • docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo

      Enumere sus contenedores en ejecución:

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f6bc2f50dff6 your_dockerhub_username/nodejs-image-demo "node app.js" 4 seconds ago Up 3 seconds 0.0.0.0:80->8080/tcp nodejs-image-demo

      Visite http://your_server_ip una vez más para ver su aplicación en ejecución.

      Conclusión

      En este tutorial, creó una aplicación web estática con Express y Bootstrap, así como una imagen de Docker para la aplicación. Utilizó esta imagen para crear un contenedor y la insertó en Docker Hub. Desde allí, pudo destruir su imagen y su contenedor, y recrearlos usando su repositorio de Docker Hub.

      Si le interesa aprender más sobre cómo trabajar con herramientas como Docker Compose y Docker Machine para crear configuraciones de múltiples contenedores, puede consultar las siguientes guías:

      Para obtener sugerencias generales sobre el trabajo con los datos del contenedor, consulte:

      Si le interesan otros temas relacionados con Docker, consulte nuestra biblioteca completa de tutoriales de Docker.



      Source link

      Cómo instalar y usar Docker en Debian 9


      finid escribió una versión anterior de este tutorial.

      Introducción

      Docker es una aplicación que simplifica el proceso de administración de procesos de aplicación en contenedores. Los contenedores le permiten ejecutar sus aplicaciones en procesos con aislamiento de recursos. Son similares a las máquinas virtuales, pero los contenedores son más portátiles, más flexibles con los recursos y más dependientes del sistema operativo host.

      Para hallar una introducción detallada a los distintos componentes de un contenedor de Docker, consulte El ecosistema de Docker: Introducción a los componentes comunes.

      A través de este tutorial, instalará y usará Docker Community Edition (CE) en Debian 9. Instalará el propio Docker, trabajará con contenedores e imágenes, e introducirá una imagen en un repositorio Docker.

      Requisitos previos

      Para completar este tutorial, necesitará lo siguiente:

      Paso 1: Instalar Docker

      Es posible que la versión del paquete de instalación de Docker disponible en el repositorio oficial de Debian no sea la más reciente. Para asegurarnos de contar con la versión más reciente, instalaremos Docker desde el repositorio oficial de Docker. Para hacerlo, agregaremos una nueva fuente de paquetes y la clave GPG de Docker para garantizar que las descargas sean válidas, y luego instalaremos el paquete.

      Primero, actualice su lista de paquetes existente:

      A continuación, instale algunos paquetes de requisitos previos que permitan a apt usar paquetes a través de HTTPS:

      • sudo apt install apt-transport-https ca-certificates curl gnupg2 software-properties-common

      Luego, añada la clave de GPG para el repositorio oficial de Docker en su sistema:

      • curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -

      Agregue el repositorio de Docker a las fuentes de APT:

      • sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"

      A continuación, actualice el paquete de base de datos con los paquetes de Docker del repositorio recién agregado:

      Asegúrese de estar a punto de realizar la instalación desde el repositorio de Docker en lugar del repositorio predeterminado de Debian:

      • apt-cache policy docker-ce

      Si bien el número de versión de Docker puede ser distinto, verá un resultado como el siguiente:

      Output of apt-cache policy docker-ce

      docker-ce:
        Installed: (none)
        Candidate: 18.06.1~ce~3-0~debian
        Version table:
           18.06.1~ce~3-0~debian 500
              500 https://download.docker.com/linux/debian stretch/stable amd64 Packages
      

      Observe que docker-ce no está instalado, pero la opción más viable para la instalación es del repositorio de Docker para Debian 9 (stretch).

      Por último, instale Docker:

      • sudo apt install docker-ce

      Con esto, Docker quedará instalado, el demonio se iniciará y el proceso se habilitará para ejecutarse en el inicio. Compruebe que funcione:

      • sudo systemctl status docker

      El resultado debe ser similar al siguiente, y mostrar que el servicio está activo y en ejecución:

      Output

      ● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2018-07-05 15:08:39 UTC; 2min 55s ago Docs: https://docs.docker.com Main PID: 21319 (dockerd) CGroup: /system.slice/docker.service ├─21319 /usr/bin/dockerd -H fd:// └─21326 docker-containerd --config /var/run/docker/containerd/containerd.toml

      La instalación de Docker ahora le proporcionará no solo el servicio de Docker (demonio) sino también la utilidad de línea de comandos docker o el cliente de Docker. Más adelante, exploraremos la forma de usar el comando docker en este tutorial.

      Paso 2 : Ejecutar el comando Docker sin sudo (opcional)

      Por defecto, el comando docker solo puede ser ejecutado por el usuario root o un usuario del grupo docker, que se crea automáticamente durante el proceso de instalación de Docker. Si intenta ejecutar el comando docker sin sudo como prefijo o sin formar parte del grupo docker, obtendrá un resultado como este:

      Output

      docker: Cannot connect to the Docker daemon. Is the docker daemon running on this host?. See 'docker run --help'.

      Si desea evitar escribir sudo al ejecutar el comando docker, agregue su nombre de usuario al grupo docker:

      • sudo usermod -aG docker ${USER}

      Para aplicar la nueva membresía de grupo, cierre la sesión del servidor y vuelva a iniciarla o escriba lo siguiente:

      Para continuar, se le solicitará ingresar la contraseña de su usuario.

      Confirme que ahora su usuario se agregó al grupo docker escribiendo lo siguiente:

      Output

      sammy sudo docker

      Si debe agregar al grupo docker un usuario con el que no inició sesión, declare dicho nombre de usuario de forma explícita usando lo siguiente:

      • sudo usermod -aG docker username

      Para el resto de este artículo, se supone que ejecutará el comando docker como usuario del grupo docker. Si elige no hacerlo, incluya sudo al principio de los comandos.

      A continuación, exploremos el comando docker.

      Paso 3: Usar el comando docker

      El uso de docker consiste en pasar a este una cadena de opciones y comandos seguida de argumentos. La sintaxis adopta esta forma:

      • docker [option] [command] [arguments]

      Para ver todos los subcomandos disponibles, escriba lo siguiente:

      A partir de Docker 18, en la lista completa de subcomandos disponibles se incluye lo siguiente:

      Output

      attach Attach local standard input, output, and error streams to a running container build Build an image from a Dockerfile commit Create a new image from a container's changes cp Copy files/folders between a container and the local filesystem create Create a new container diff Inspect changes to files or directories on a container's filesystem events Get real time events from the server exec Run a command in a running container export Export a container's filesystem as a tar archive history Show the history of an image images List images import Import the contents from a tarball to create a filesystem image info Display system-wide information inspect Return low-level information on Docker objects kill Kill one or more running containers load Load an image from a tar archive or STDIN login Log in to a Docker registry logout Log out from a Docker registry logs Fetch the logs of a container pause Pause all processes within one or more containers port List port mappings or a specific mapping for the container ps List containers pull Pull an image or a repository from a registry push Push an image or a repository to a registry rename Rename a container restart Restart one or more containers rm Remove one or more containers rmi Remove one or more images run Run a command in a new container save Save one or more images to a tar archive (streamed to STDOUT by default) search Search the Docker Hub for images start Start one or more stopped containers stats Display a live stream of container(s) resource usage statistics stop Stop one or more running containers tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE top Display the running processes of a container unpause Unpause all processes within one or more containers update Update configuration of one or more containers version Show the Docker version information wait Block until one or more containers stop, then print their exit codes

      Si desea ver las opciones disponibles para un comando específico, escriba lo siguiente:

      • docker docker-subcommand --help

      Para ver información sobre Docker relacionada con todo el sistema, utilice lo siguiente:

      Exploremos algunos de estos comandos. Comenzaremos trabajando con imágenes.

      Paso 4: Trabajar con imágenes de Docker

      Los contenedores de Docker se construyen con imágenes de Docker. Por defecto, Docker obtiene estas imágenes de Docker Hub, un registro de Docker gestionado por Docker, la empresa responsable del proyecto Docker. Cualquiera puede alojar sus imágenes en Docker Hub, de modo que la mayoría de las aplicaciones y las distribuciones de Linux que necesitará tendrán imágenes alojadas allí.

      Para verificar si puede acceder a imágenes y descargarlas de Docker Hub, escriba lo siguiente:

      El resultado indicará que Docker funciona de forma correcta:

      Output

      Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 9db2ca6ccae0: Pull complete Digest: sha256:4b8ff392a12ed9ea17784bd3c9a8b1fa3299cac44aca35a85c90c5e3c7afacdc Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. ...

      Inicialmente, Docker no pudo encontrar la imagen de hello-world a nivel local. Por ello la descargó de Docker Hub, el repositorio predeterminado. Una vez que se descargó la imagen, Docker creó un contenedor a partir de ella y de la aplicación dentro del contenedor ejecutado, y mostró el mensaje.

      Puede buscar imágenes disponibles en Docker Hub usando el comando docker con el subcomando search. Por ejemplo, para buscar la imagen de Ubuntu, escriba lo siguiente:

      El script rastreará Docker Hub y mostrará una lista de todas las imágenes cuyo nombre coincida con la cadena de búsqueda. En este caso, el resultado será similar a lo siguiente:

      Output

      NAME DESCRIPTION STARS OFFICIAL AUTOMATED ubuntu Ubuntu is a Debian-based Linux operating sys… 8320 [OK] dorowu/ubuntu-desktop-lxde-vnc Ubuntu with openssh-server and NoVNC 214 [OK] rastasheep/ubuntu-sshd Dockerized SSH service, built on top of offi… 170 [OK] consol/ubuntu-xfce-vnc Ubuntu container with "headless" VNC session… 128 [OK] ansible/ubuntu14.04-ansible Ubuntu 14.04 LTS with ansible 95 [OK] ubuntu-upstart Upstart is an event-based replacement for th… 88 [OK] neurodebian NeuroDebian provides neuroscience research s… 53 [OK] 1and1internet/ubuntu-16-nginx-php-phpmyadmin-mysql-5 ubuntu-16-nginx-php-phpmyadmin-mysql-5 43 [OK] ubuntu-debootstrap debootstrap --variant=minbase --components=m… 39 [OK] nuagebec/ubuntu Simple always updated Ubuntu docker images w… 23 [OK] tutum/ubuntu Simple Ubuntu docker images with SSH access 18 i386/ubuntu Ubuntu is a Debian-based Linux operating sys… 13 1and1internet/ubuntu-16-apache-php-7.0 ubuntu-16-apache-php-7.0 12 [OK] ppc64le/ubuntu Ubuntu is a Debian-based Linux operating sys… 12 eclipse/ubuntu_jdk8 Ubuntu, JDK8, Maven 3, git, curl, nmap, mc, … 6 [OK] darksheer/ubuntu Base Ubuntu Image -- Updated hourly 4 [OK] codenvy/ubuntu_jdk8 Ubuntu, JDK8, Maven 3, git, curl, nmap, mc, … 4 [OK] 1and1internet/ubuntu-16-nginx-php-5.6-wordpress-4 ubuntu-16-nginx-php-5.6-wordpress-4 3 [OK] pivotaldata/ubuntu A quick freshening-up of the base Ubuntu doc… 2 1and1internet/ubuntu-16-sshd ubuntu-16-sshd 1 [OK] ossobv/ubuntu Custom ubuntu image from scratch (based on o… 0 smartentry/ubuntu ubuntu with smartentry 0 [OK] 1and1internet/ubuntu-16-healthcheck ubuntu-16-healthcheck 0 [OK] pivotaldata/ubuntu-gpdb-dev Ubuntu images for GPDB development 0 paasmule/bosh-tools-ubuntu Ubuntu based bosh-cli 0 [OK] ...

      En la columna de OFFICIAL,** OK** indica una imagen creada y avalada por la empresa responsable del proyecto. Una vez que identifique la imagen que desearía usar, puede descargarla a su computadora usando el subcomando pull.

      Ejecute el siguiente comando para descargar la imagen oficial de ubuntu a su ordenador:

      Verá el siguiente resultado:

      Output

      Using default tag: latest latest: Pulling from library/ubuntu 6b98dfc16071: Pull complete 4001a1209541: Pull complete 6319fc68c576: Pull complete b24603670dc3: Pull complete 97f170c87c6f: Pull complete Digest: sha256:5f4bdc3467537cbbe563e80db2c3ec95d548a9145d64453b06939c4592d67b6d Status: Downloaded newer image for ubuntu:latest

      Una vez descargada una imagen, puede ejecutar un contenedor usando la imagen descargada con el subcomando run. Como pudo ver en el ejemplo de hello-world, si no se descargó una imagen al ejecutarse docker con el subcomando run, el cliente de Docker descargará primero la imagen y luego ejecutará un contenedor utilizándola.

      Para ver las imágenes descargadas a su computadora, escriba lo siguiente:

      El resultado debe tener un aspecto similar al siguiente:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest 16508e5c265d 13 days ago 84.1MB hello-world latest 2cb0d9787c4d 7 weeks ago 1.85kB

      Como verá más adelante en este tutorial, las imágenes que utilice para ejecutar contenedores pueden modificarse y utilizarse para generar nuevas imágenes que se pueden cargar posteriormente (“introducir” es el término técnico) a Docker Hub o a otros registros de Docker.

      Veamos en mayor profundidad la forma de ejecutar los contenedores.

      Paso 5: Ejecutar un contenedor de Docker

      El contenedor hello-world que ejecutó en el paso anterior es un ejemplo de un contenedor que se ejecuta y se cierra tras emitir un mensaje de prueba. Los contenedores pueden ofrecer una utilidad mucho mayor y ser interactivos. Después de todo, son similares a las máquinas virtuales, aunque más flexibles con los recursos.

      Como ejemplo, ejecutemos un contenedor usando la imagen más reciente de Ubuntu. La combinación de los conmutadores -i y -t le proporcionan un acceso interactivo del shell al contenedor:

      Su símbolo del sistema debe cambiar para reflejar el hecho de que ahora trabaja dentro del contenedor y debe adoptar esta forma:

      Output

      root@d9b100f2f636:/#

      Tenga en cuenta el ID del contenedor en el símbolo del sistema. En este ejemplo, es d9b100f2f636. Más adelante, necesitará ese ID de contenedor para identificar el contenedor cuando desee eliminarlo.

      Ahora puede ejecutar cualquier comando dentro del contenedor. Por ejemplo, actualicemos la base de datos del paquete dentro del contenedor. No es necesario prefijar ningún comando con sudo, ya que realiza operaciones dentro del contenedor como el usuario root:

      Luego, instale cualquier aplicación en él. Probemos con Node.js:

      Con esto, se instala Node.js en el contenedor desde el repositorio oficial de Ubuntu. Cuando finalice la instalación, verifique que Node.js esté instalado:

      Verá el número de versión en su terminal:

      Output

      v8.10.0

      Cualquier cambio que realice dentro del contenedor solo se aplica a este.

      Para cerrar el contenedor, escriba exit a línea de comandos.

      A continuación, veremos la forma de administrar los contenedores en nuestro sistema.

      Paso 6: Administrar contenedores de Docker

      Después de usar Docker durante un tiempo, tendrá muchos contenedores activos (en ejecución) e inactivos en su computadora. Para ver *los *activos, utilice lo siguiente:

      Verá una salida similar a la siguiente:

      Output

      CONTAINER ID IMAGE COMMAND CREATED

      A través de este tutorial, inició dos contenedores: uno de la imagen hello-world y otro de la imagen ubuntu. Ambos contenedores ya no están en ejecución, pero aún existen en su sistema.

      Para ver todos los contenedores, activos e inactivos, ejecute docker ps con el conmutador -a:

      Visualizará un resultado similar a esto:

      d9b100f2f636        ubuntu              "/bin/bash"         About an hour ago   Exited (0) 8 minutes ago                           sharp_volhard
      01c950718166        hello-world         "/hello"            About an hour ago   Exited (0) About an hour ago                       festive_williams
      
      

      Para ver el último contenedor que creó, páselo al conmutador -l:

      • CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
      • d9b100f2f636 ubuntu "/bin/bash" About an hour ago Exited (0) 10 minutes ago sharp_volhard

      Para iniciar un contenedor detenido, utilice docker start, seguido del o el nombre ID del contenedor. Iniciemos el contenedor basado en Ubuntu con el ID de d9b100f2f636:

      • docker start d9b100f2f636

      El contenedor se iniciará y podrá usar docker ps para ver su estado:

      CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
      d9b100f2f636        ubuntu              "/bin/bash"         About an hour ago   Up 8 seconds                            sharp_volhard
      
      

      Para detener un contenedor en funcionamiento, utilice docker stop, seguido del ID o nombre del contenedor. Esta vez usaremos el nombre que Docker asignó al contenedor, que es sharp_volhard:

      • docker stop sharp_volhard

      Una vez que decidida que ya no necesita un contenedor, elimínelo con el comando docker rm y use nuevamente el ID o el nombre del contenedor. Utilice el comando docker ps -a para encontrar el ID o nombre del contenedor asociado con la imagen hello-world y elimínelo.

      • docker rm festive_williams

      Puede iniciar un nuevo contenedor y darle un nombre usando el conmutador --name. También podrá usar el conmutador de --rm para crear un contenedor que se elimine de forma automática cuando se detenga. Consulte el comando docker run help para obtener más información sobre estas y otras opciones.

      Los contenedores pueden convertirse en imágenes que podrá usar para crear contenedores nuevos. Veamos cómo funciona esto.

      Paso 7: Confirmar cambios aplicados a una imagen de Docker en un contenedor

      Cuando inicie una imagen de Docker, podrá crear, modificar y eliminar archivos del mismo modo que con una máquina virtual. Los cambios que realice solo se aplicarán al contenedor en cuestión. Podrá iniciarlo y detenerlo, pero una vez que lo destruya con el comando docker rm, los cambios se perderán por completo.

      En esta sección verá la forma de guardar el estado de un contenedor como una nueva imagen de Docker.

      Después de instalar Node.js dentro del contenedor de Ubuntu, dispondrá de un contenedor que se ejecuta a partir de una imagen, pero este es diferente de la imagen que utilizó para crearlo. Sin embargo, quizá desee reutilizar este contenedor Node.js como base de nuevas imágenes posteriormente.

      Luego, confirme los cambios en una nueva instancia de imagen de Docker utilizando el siguiente comando:

      • docker commit -m "What you did to the image" -a "Author Name" container_id repository/new_image_name

      El conmutador -m es para el mensaje de confirmación que le permite a usted y a otros a saber qué cambios realizaron, mientras que -a se utiliza para especificar el autor. El container_id es el que observó anteriormente en el tutorial cuando inició la sesión interactiva de Docker. A menos que haya creado repositorios adicionales en Docker Hub, repository generalmente corresponde a su nombre de usuario de Docker Hub.

      Por ejemplo, para el usuario** sammy**, con el ID de contenedor d9b100f26f636, el comando sería el siguiente:

      • docker commit -m "added Node.js" -a "sammy" d9b100f2f636 sammy/ubuntu-nodejs

      Cuando *confirme *una imagen, la nueva imagen se guardará a nivel local en su computadora. Más adelante, en este tutorial, aprenderá a introducir una imagen en un registro de Docker como Docker Hub para que otros puedan acceder a ella.

      Listar las imágenes de Docker de nuevo mostrará la nueva imagen, así como la anterior de la que se derivó:

      Verá resultados como este:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE sammy/ubuntu-nodejs latest 7c1f35226ca6 7 seconds ago 179MB ubuntu latest 113a43faa138 4 weeks ago 81.2MB hello-world latest e38bc07ac18e 2 months ago 1.85kB

      En este ejemplo ubuntu-nodejs es la nueva imagen, derivada de la imagen ubuntu existente de Docker Hub. La diferencia de tamaño refleja los cambios realizados. En este ejemplo, el cambio fue la instalación de NodeJS. Por ello, la próxima vez que deba ejecutar un contenedor usando Ubuntu con NodeJS preinstalado, podrá usar simplemente la nueva imagen.

      También podrá crear imágenes de un Dockerfile, lo cual le permitirá automatizar la instalación de software en una nueva imagen. Sin embargo, eso queda fuera del alcance de este tutorial.

      Ahora, compartiremos la nueva imagen con terceros para que puedan crear contenedores a partir de ella.

      Paso 8: Introducir imágenes de Docker en un repositorio de Docker

      El siguiente paso lógico después de crear una nueva imagen a partir de una imagen existente es compartirla con algunos de sus amigos, con todo el mundo en Docker Hub, o en otro registro de Docker al que tenga acceso. Para introducir una imagen a Docker Hub o a cualquier otro registro de Docker, deberá tener una cuenta en el sistema.

      En esta sección verá cómo introducir una imagen de Docker en Docker Hub. Para aprender a crear su propio registro privado de Docker, consulte Cómo configurar un registro de Docker privado en Ubuntu 14.04.

      Para introducir su imagen, primero inicie sesión en Docker Hub.

      • docker login -u docker-registry-username

      Se le solicitará autenticarse usando su contraseña de Docker Hub. Si especificó la contraseña correcta, la autenticación tendrá éxito.

      Nota: Si su nombre de usuario de registro de Docker es diferente del nombre de usuario local que usó para crear la imagen, deberá etiquetar su imagen con su nombre de usuario de registro. Para el ejemplo que se muestra en el último paso, deberá escribir lo siguiente:

      • docker tag sammy/ubuntu-nodejs docker-registry-username/ubuntu-nodejs

      Luego podrá introducir su propia imagen usando lo siguiente:

      • docker push docker-registry-username/docker-image-name

      Para introducir la imagen ubuntu-nodejs en el repositorio de sammy, el comando sería el siguiente:

      • docker push sammy/ubuntu-nodejs

      El proceso puede tardar un tiempo en completarse cuando se suben las imágenes, pero una vez que finalice el resultado será el siguiente:

      Output

      The push refers to a repository [docker.io/sammy/ubuntu-nodejs] e3fbbfb44187: Pushed 5f70bf18a086: Pushed a3b5c80a4eba: Pushed 7f18b442972b: Pushed 3ce512daaf78: Pushed 7aae4540b42d: Pushed ...

      Una vez que introduce una imagen en un registro, esta debe aparecer en el panel de su cuenta, como se muestra en la siguiente captura:

      Nuevo listado de imágenes de Docker en Docker Hub

      Si un intento de introducción produce un error de este tipo, es probable que no haya iniciado sesión:

      Output

      The push refers to a repository [docker.io/sammy/ubuntu-nodejs] e3fbbfb44187: Preparing 5f70bf18a086: Preparing a3b5c80a4eba: Preparing 7f18b442972b: Preparing 3ce512daaf78: Preparing 7aae4540b42d: Waiting unauthorized: authentication required

      Inicie sesión con docker login y repita el intento de introducción. Luego, compruebe que exista en su página de repositorios de Docker Hub.

      Ahora podrá usar ​​​​​​​docker ​​​​​​pull sammy​​​/ubuntu-nodejs​​​​​​​​​​​​ para introducir la imagen en una nueva máquina y usarla para ejecutar un nuevo contenedor.

      Conclusión

      A través de este tutorial, instaló Docker, trabajó con imágenes y contenedores e introdujo una imagen modificada en Docker Hub. Ahora que conoce los aspectos básico, explore los otros tutoriales de Docker de la Comunidad de DigitalOcean.



      Source link

      Cómo configurar Laravel, Nginx y MySQL con Docker Compose


      El autor seleccionó a The FreeBSD Foundation para recibir una donación como parte del programa Write for DOnations.

      Introducción

      Durante los últimos años, Docker se ha convertido en una solución de uso frecuente para implementar aplicaciones gracias a la forma en que simplifican el funcionamiento y la implementación de aplicaciones en contenedores efímeros. Cuando se usa una pila de aplicación LEMP, por ejemplo, con PHP, Nginx, MySQL y el framework de Laravel, Docker puede simplificar considerablemente el proceso de configuración.

      Docker Compose ha simplificado aún más el proceso de desarrollo al permitir que los desarrolladores definan su infraestructura, incluidos los servicios de aplicación, las redes y los volúmenes, en un único archivo. Docker Compose ofrece una alternativa eficaz para ejecutar varios comandos docker container create y docker container run.

      A través de este tutorial, creará una aplicación web utilizando el marco Laravel con Nginx como servidor web y MySQL como base de datos; todo ello dentro de contenedores de Docker. Definirá toda la configuración de pila en un archivo docker-compose, junto con los archivos de configuración para PHP, MySQL y Nginx.

      Requisitos previos

      Antes de comenzar, necesitará lo siguiente:

      Paso 1: Descargar Laravel e instalar dependencias

      Como primer paso, obtendremos la versión más reciente de Laravel e instalaremos las dependencias del proyecto. Incluiremos Composer, el administrador de paquetes de nivel de aplicación para PHP. Instalaremos estas dependencias con Docker para evitar la instalación de Composer a nivel global.

      Primero, compruebe que se encuentre en su directorio de inicio, clone la última versión de Laravel y dispóngala en un directorio llamado laravel-app:

      • cd ~
      • git clone https://github.com/laravel/laravel.git laravel-app

      Posiciónese en el directorio laravel-app:“

      A continuación, utilice la imagen de composer de Docker a fin de montar los directorios que necesitará para su proyecto de Laravel y evitar la sobrecarga que implica instalar Composer a nivel global:

      • docker run --rm -v $(pwd):/app composer install

      Mediante los indicadores -v y --rm con docker run se crea un contenedor efímero para el cual se aplica un montaje “bind” a la lista de comandos actual antes de su eliminación. Con esto, se copiará el contenido de su directorio ~/laravel-app al contenedor y también se garantizará que la carpeta vendor creada por Composer dentro del contenedor se copie a su directorio actual.

      Como paso final, establezca permisos en el directorio del proyecto para que sea propiedad de su usuario no root:

      • sudo chown -R $USER:$USER ~/laravel-app

      Esto será importante al escribir el Dockerfile para la imagen de su aplicación en el paso 4, ya que le permitirá trabajar con el código de la aplicación y ejecutar procesos en su contenedor como usuario no root.

      Una vez establecido el código de su aplicación, puede proceder a definir sus servicios con Docker Compose.

      Paso 2: Crear el archivo de Docker Compose

      Desarrollar sus aplicaciones con Docker Compose simplifica el proceso de configuración y control de versiones de su infraestructura. Para configurar nuestra aplicación de Laravel, escribiremos un archivo docker-compose que defina nuestro servidor web, nuestra base de datos y nuestros servicios de aplicación.

      Abra el archivo:

      • nano ~/laravel-app/docker-compose.yml

      En el archivo docker-compose, definirá tres servicios: app, webserver y db. Agregue el siguiente código al archivo, asegúrese de sustituir la contraseña root de MySQL_ROOT_PASSWORD, definida como una variable de entorno bajo el servicio db, por una contraseña segura de su elección:

      ~/laravel-app/docker-compose.yml

      version: '3'
      services:
      
        #PHP Service
        app:
          build:
            context: .
            dockerfile: Dockerfile
          image: digitalocean.com/php
          container_name: app
          restart: unless-stopped
          tty: true
          environment:
            SERVICE_NAME: app
            SERVICE_TAGS: dev
          working_dir: /var/www
          networks:
            - app-network
      
        #Nginx Service
        webserver:
          image: nginx:alpine
          container_name: webserver
          restart: unless-stopped
          tty: true
          ports:
            - "80:80"
            - "443:443"
          networks:
            - app-network
      
        #MySQL Service
        db:
          image: mysql:5.7.22
          container_name: db
          restart: unless-stopped
          tty: true
          ports:
            - "3306:3306"
          environment:
            MYSQL_DATABASE: laravel
            MYSQL_ROOT_PASSWORD: your_mysql_root_password
            SERVICE_TAGS: dev
            SERVICE_NAME: mysql
          networks:
            - app-network
      
      #Docker Networks
      networks:
        app-network:
          driver: bridge
      

      Los servicios definidos aquí incluyen lo siguiente:

      • app: esta definición de servicio contiene la aplicación de Laravel y ejecuta una imagen personalizada de Docker, digitalocean.com/php, que usted definirá en el paso 4. También fija /var/www para working_dir en el contenedor.
      • webserver: esta definición de servicio obtiene la imagen nginx:alpine de Docker y expone los puertos 80 y 443.
      • db: esta definición de servicio obtiene la imagen mysql:5.7.22 de Docker y define algunas variables de entorno, incluida una base de datos llamada laravel para su aplicación y la contraseña root para la base de datos. Puede nombrar la base de datos como lo desee y debe sustituir your_mysql_root_password por su propia contraseña segura. Esta definición de servicio también asigna el puerto 3306 en el host al puerto 3306 en el contenedor.

      Cada propiedad container_name define un nombre para el contenedor, que corresponde al nombre del servicio. Si no define esta propiedad, Docker asignará un nombre a cada contenedor combinando el nombre de una persona históricamente famosa y una palabra al azar separada por un guión bajo.

      Para facilitar la comunicación entre contenedores, los servicios se conectan a una red de puente llamada app-network. Una red de puente utiliza un puente de software que permite que los contenedores conectados a la misma red de puente se comuniquen entre sí. El controlador de puente instala de forma automática reglas en la máquina host para que los contenedores de diferentes redes de puente no puedan comunicarse directamente entre sí. Esto crea un mayor nivel de seguridad para las aplicaciones y garantiza que solo los servicios relacionados puedan comunicarse entre sí. También implica que usted puede definir diferentes redes y servicios que se conectan a funciones relacionadas: los servicios de aplicaciones clientes pueden utilizar una red frontend, por ejemplo, y los servicios de servidor pueden usar una red backend.

      Veamos la forma de agregar volúmenes y montajes “bind” a sus definiciones de servicio para persistir los datos de su aplicación.

      Paso 3: Persistir datos

      Docker tiene características potentes y convenientes para la persistencia de datos. En nuestra aplicación, usaremos volúmenes y montajes bind para persistir la base de datos y los archivos de aplicación y configuración. Los volúmenes ofrecen flexibilidad para los respaldos y la persistencia más allá del ciclo de vida de un contenedor, mientras que los montajes “bind” facilitan los cambios de código durante el desarrollo y realizan cambios en los archivos host o directorios disponibles de inmediato en sus contenedores. En nuestra configuración usaremos ambas opciones.

      Advertencia: Al usar de montajes “bind”, permite cambiar el sistema de archivos host a través de procesos que se ejecutan en un contenedor. Se incluye la creación, modificación o eliminación de archivos o directorios importantes del sistema. Esta es una poderosa capacidad que tiene consecuencias para la seguridad y podría afectar a los procesos no Docker del sistema host. Use los montajes “bind” con cuidado.

      En el archivo docker-compose, defina un volumen llamado dbdata bajo la definición de servicio db para persistir la base de datos de MySQL:

      ~/laravel-app/docker-compose.yml

      ...
      #MySQL Service
      db:
        ...
          volumes:
            - dbdata:/var/lib/mysql
          networks:
            - app-network
        ...
      

      El volumen llamado dbdata persiste el contenido de la carpeta /var/lib/mysql situada dentro del contenedor. Esto le permite detener y reiniciar el servicio db sin perder datos.

      En la parte inferior del archivo, agregue la definición para el volumen dbdata:

      ~/laravel-app/docker-compose.yml

      ...
      #Volumes
      volumes:
        dbdata:
          driver: local
      

      Una vez implementada esta definición, podrá utilizar este volumen en todos los servicios.

      A continuación, agregue un montaje “bind” al servicio db para los archivos de configuración de MySQL que creará en el paso 7:

      ~/laravel-app/docker-compose.yml

      ...
      #MySQL Service
      db:
        ...
          volumes:
            - dbdata:/var/lib/mysql
            - ./mysql/my.cnf:/etc/mysql/my.cnf
        ...
      

      Este montaje “bind” vincula ~/laravel-app/mysql/my.cnf a /etc/mysql/my.cnf en el contenedor.

      A continuación, agregue montajes “bind” al servicio webserver. Habrá dos: uno para el código de su aplicación y otro para la definición de configuración de Nginx que creará en el paso 6:

      ~/laravel-app/docker-compose.yml

      #Nginx Service
      webserver:
        ...
        volumes:
            - ./:/var/www
            - ./nginx/conf.d/:/etc/nginx/conf.d/
        networks:
            - app-network
      

      El primer montaje “bind” vincula el código de la aplicación situado en el directorio ~/laravel-app al directorio /var/www dentro del contenedor. El archivo de configuración que agregará a ~/laravel-app/nginx/conf.d/ también se montará a /etc/nginx/conf.d/ en el contenedor, lo que le permitirá agregar o modificar el contenido del directorio de configuración cuando sea necesario.

      Por último, agregue los siguientes montajes “bind” al servicio app para el código de la aplicación y los archivos de configuración:

      ~/laravel-app/docker-compose.yml

      #PHP Service
      app:
        ...
        volumes:
             - ./:/var/www
             - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
        networks:
            - app-network
      

      El servicio app vincula mediante montaje “bind” la carpeta ~/laravel-app, que contiene el código de la aplicación, a la carpeta /var/www en el contenedor. Esto acelerará el proceso de desarrollo, ya que los cambios realizados en el directorio de su aplicación local se reflejarán de inmediato dentro del contenedor. También vinculará su archivo de configuración PHP, ~/laravel-app/php/local.ini, a /usr/local/etc/php/conf.d/local.ini, dentro del contenedor. Creará el archivo de configuración de PHP local en el paso 5.

      Ahora, su archivo docker-compose tendrá el siguiente aspecto:

      ~/laravel-app/docker-compose.yml

      version: '3'
      services:
      
        #PHP Service
        app:
          build:
            context: .
            dockerfile: Dockerfile
          image: digitalocean.com/php
          container_name: app
          restart: unless-stopped
          tty: true
          environment:
            SERVICE_NAME: app
            SERVICE_TAGS: dev
          working_dir: /var/www
          volumes:
            - ./:/var/www
            - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
          networks:
            - app-network
      
        #Nginx Service
        webserver:
          image: nginx:alpine
          container_name: webserver
          restart: unless-stopped
          tty: true
          ports:
            - "80:80"
            - "443:443"
          volumes:
            - ./:/var/www
            - ./nginx/conf.d/:/etc/nginx/conf.d/
          networks:
            - app-network
      
        #MySQL Service
        db:
          image: mysql:5.7.22
          container_name: db
          restart: unless-stopped
          tty: true
          ports:
            - "3306:3306"
          environment:
            MYSQL_DATABASE: laravel
            MYSQL_ROOT_PASSWORD: your_mysql_root_password
            SERVICE_TAGS: dev
            SERVICE_NAME: mysql
          volumes:
            - dbdata:/var/lib/mysql/
            - ./mysql/my.cnf:/etc/mysql/my.cnf
          networks:
            - app-network
      
      #Docker Networks
      networks:
        app-network:
          driver: bridge
      #Volumes
      volumes:
        dbdata:
          driver: local
      

      Guarde el archivo y cierre su editor cuando termine de realizar cambios.

      Ahora que su archivo docker-compose está escrito, podrá crear la imagen personalizada para su aplicación.

      Paso 4: Crear el Dockerfile

      Docker le permite especificar el entorno dentro de contenedores individuales con un Dockerfile. Un Dockerfile le permite crear imágenes personalizadas que puede emplear para instalar el software requerido por su aplicación y configurar los ajustes según sus requisitos. Puede introducir en Docker Hub o en cualquier registro privado las imágenes personalizadas que cree.

      Nuestro Dockerfile se ubicará en nuestro directorio ~/laravel-app. Cree el archivo:

      • nano ~/laravel-app/Dockerfile

      Este Dockerfile establecerá la imagen de base y especificará los comandos y las instrucciones que se necesitan para crear la imagen de aplicación de Laravel. Agregue el siguiente código al archivo:

      ~/laravel-app/php/Dockerfile

      FROM php:7.2-fpm
      
      # Copy composer.lock and composer.json
      COPY composer.lock composer.json /var/www/
      
      # Set working directory
      WORKDIR /var/www
      
      # Install dependencies
      RUN apt-get update && apt-get install -y 
          build-essential 
          mysql-client 
          libpng-dev 
          libjpeg62-turbo-dev 
          libfreetype6-dev 
          locales 
          zip 
          jpegoptim optipng pngquant gifsicle 
          vim 
          unzip 
          git 
          curl
      
      # Clear cache
      RUN apt-get clean && rm -rf /var/lib/apt/lists/*
      
      # Install extensions
      RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl
      RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/
      RUN docker-php-ext-install gd
      
      # Install composer
      RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
      
      # Add user for laravel application
      RUN groupadd -g 1000 www
      RUN useradd -u 1000 -ms /bin/bash -g www www
      
      # Copy existing application directory contents
      COPY . /var/www
      
      # Copy existing application directory permissions
      COPY --chown=www:www . /var/www
      
      # Change current user to www
      USER www
      
      # Expose port 9000 and start php-fpm server
      EXPOSE 9000
      CMD ["php-fpm"]
      

      Primero, el Dockerfile crea una imagen en la parte superior de la imagen de php:7.2-fpm Docker. Esta es una imagen basada en Debian que tiene instalada la implementación PHP-FPM de PHP FastCGI. El archivo también instala con composer los paquetes previos para Laravel: mcrypt, pdo_mysql, mbstring e imagick.

      La directiva RUN especifica los comandos para actualizar, instalar y configurar los ajustes dentro del contenedor. Esto incluye la creación de un usuario dedicado y un grupo llamado www. La instrucción WORKDIR especifica el directorio /var/www como directorio de trabajo para la aplicación.

      Crear un usuario dedicado y un grupo con permisos restringidos mitiga la vulnerabilidad inherente al ejecutar contenedores de Docker, que se funcionan por defecto como root. En lugar de ejecutar este contenedor como root, creamos el usuario** www**, que tiene acceso de lectura y escritura a la carpeta /var/www gracias a la instrucción COPY que usaremos con el indicador --chown para copiar los permisos de la carpeta de la aplicación.

      Por último, el comando EXPOSE expone un puerto del contenedor, el 9000, para el servidor php-fpm. CMD especifica el comando que debe ejecutarse una vez que se cree el contenedor. Aquí, el CMD especifica “php-fpm”, que iniciará el servidor.

      Guarde el archivo y cierre su editor cuando termine de realizar cambios.

      Ahora podrá definir su configuración de PHP.

      Paso 5: Configurar PHP

      Ahora que definió su infraestructura en el archivo docker-compose, puede configurar el servicio PHP para que funciones como procesador PHP para solicitudes entrantes de Nginx.

      Para configurar PHP, creará el archivo local.ini dentro de la carpeta php. Este es el archivo que vinculó mediante montaje “bind” a /usr/local/etc/php/conf.d/local.ini dentro del contenedor en el paso 2. Crear este archivo le permitirá anular el archivo php.ini predeterminado que PHP lee al iniciarse.

      Cree el directorio php:

      A continuación, abra el archivo local.ini:

      • nano ~/laravel-app/php/local.ini

      Con el propósito de demostrar cómo configurar PHP, agregaremos el siguiente código para establecer limitaciones de tamaño para archivos cargados:

      ~/laravel-app/php/local.ini

      upload_max_filesize=40M
      post_max_size=40M
      

      Las directivas upload_max_filesize y post_max_size establecen el tamaño máximo permitido para los archivos cargados y demuestran la forma en que puede configurar parámetros php.ini desde su archivo local.ini. Puede disponer cualquier configuración específica de PHP que desee anular en el archivo local.ini.

      Guarde el archivo y cierre el editor.

      Una vez preparado su archivo PHP local.ini, podrá configurar Nginx.

      Paso 6: Configurar Nginx

      Una vez configurado el servicio PHP, podrá modificar el servicio Nginx para usar PHP-FPM como servidor de FastCGI para proporcionar contenido dinámico. El servidor FastCGI se basa en un protocolo binario para interconectar programas interactivos con un servidor web. Para obtener más información, consulte este artículo sobre Comprensión e implementación de proxy de FastCGI en Nginx.

      Para configurar Nginx, creará un archivo app.conf con la configuración del servicio en la carpeta ~/laravel-app/nginx/conf.d/.

      Primero, cree el directorio nginx/conf.d/:

      • mkdir -p ~/laravel-app/nginx/conf.d

      Luego, cree el archivo de configuración app.conf:

      • nano ~/laravel-app/nginx/conf.d/app.conf

      Agregue el siguiente código al archivo para especificar su configuración de Nginx:

      ~/laravel-app/nginx/conf.d/app.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;
          }
      }
      

      El bloque de servidor define la configuración para el servidor web de Nginx con las siguientes directivas:

      • listen: esta directiva define el puerto en el cual el servidor escuchará las solicitudes entrantes.
      • error_log y access_log: estas directivas definen los archivos para escribir registros.
      • root: esta directiva establece la ruta de la carpeta root y forma la ruta para cualquier archivo solicitado en el sistema de archivos local.

      En el bloque de ubicación php, la directiva fastcgi_pass especifica que el servicio de app escuchando en un socket TCP del puerto 9000. Esto hace que el servidor PHP-FPM escuche a través de la red en lugar de hacerlo en un socket de Unix. Aunque un socket de Unix tiene una ligera ventaja de velocidad con respecto a un socket de TCP, no cuenta con un protocolo de red y, por lo tanto, omite la pila de red. Para los casos en los cuales los hosts están ubicados en una máquina, puede tener sentido la presencia de un socket de Unix. Sin embargo, en los casos en los que tenga servicios ejecutándose en diferentes hosts, un socket de TCP le ofrece la ventaja de permitirle conectarse a servicios distribuidos. Debido a que nuestro contenedor app se ejecuta en un host diferente del de nuestro contenedor webserver, un socket de TCP es la opción que más sentido tiene para nuestro tipo de configuración.

      Guarde el archivo y cierre su editor cuando termine de realizar cambios.

      Gracias al montaje “bind” mount que creó en el paso 2, cualquier cambio que realice dentro de la carpeta nginx/conf.d/ se reflejará directamente dentro del contenedor webserver.

      A continuación, observaremos nuestras configuraciones de MySQL.

      Paso 7: Configurar MySQL

      Una vez configurados PHP y Nginx, podrá habilitar MySQL para que actúe como base de datos para su aplicación.

      Para configurar MySQL, creará el archivo my.cnf en la carpeta mysql. Este es el archivo que vinculó mediante montaje “bind” a /etc/mysql/my.cnf dentro del contenedor en el paso 2. Este montaje “bind” le permite anular los ajustes de my.cnf según sea necesario.

      Para demostrar cómo funciona esto, agregaremos al archivo my.cnf ajustes que habiliten el registro general de consulta y especifiquen el archivo de registro.

      Primero, cree el directorio mysql:

      • mkdir ~/laravel-app/mysql

      A continuación, cree el archivo my.cnf:

      • nano ~/laravel-app/mysql/my.cnf

      En el archivo, agregue el siguiente código para habilitar el registro de consulta y establecer la ubicación del archivo de registro:

      ~/laravel-app/mysql/my.cnf

      [mysqld]
      general_log = 1
      general_log_file = /var/lib/mysql/general.log
      

      Este archivo my.cnf habilita los registros y define la configuración de general_log con el valor 1 para permitir registros generales. La configuración general_log_file especifica dónde se almacenarán los registros.

      Guarde el archivo y cierre el editor.

      Nuestro siguiente paso será iniciar los contenedores.

      Paso 8: Ejecutar los contenedores y modificar las preferencias de entorno

      Ahora que definió todos sus servicios en su archivo docker-compose y creó los archivos de configuración para estos servicios, puede iniciar los contenedores. Sin embargo, como paso final, crearemos una copia del archivo .env.example que Laravel incluye por defecto y daremos a la copia el nombre .env, que corresponde al archivo que Laravel prevé que definirá su entorno:

      Configuraremos los detalles específicos de nuestros ajustes en este archivo una vez que iniciemos los contenedores.

      Una vez definidos todos sus servicios en su archivo docker-compose, solo deberá emitir un comando para iniciar todos los contenedores, crear los volúmenes y configurar y conectar las redes:

      Cuando ejecute docker-compose por primera vez, descargará todas las imágenes de Docker necesarias, lo cual podría tardar un tiempo. Una vez que las imágenes se descarguen y se almacenen en su máquina local, Compose creará sus contenedores. El indicador -d agrega un demonio al proceso y ejecuta sus contenedores en segundo plano.

      Una vez que el proceso esté completo, use el siguiente comando para enumerar todos los contenedores en ejecución:

      Verá el siguiente resultado con detalles sobre sus contenedores app, webserver y db:

      Output

      CONTAINER ID NAMES IMAGE STATUS PORTS c31b7b3251e0 db mysql:5.7.22 Up 2 seconds 0.0.0.0:3306->3306/tcp ed5a69704580 app digitalocean.com/php Up 2 seconds 9000/tcp 5ce4ee31d7c0 webserver nginx:alpine Up 2 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp

      CONTAINER ID en este resultado es un identificador único para cada contenedor, mientras que NAMES enumera el nombre de servicio asociado con cada una. Puede usar ambos identificadores para acceder a los contenedores. IMAGE define el nombre de imagen para cada contenedor, mientras que STATUS proporciona información sobre el su estado: en ejecución, en proceso de reinicio o detenido.

      Ahora puede modificar el archivo .env en el contenedor app para incluir detalles específicos sobre su configuración.

      Abra el archivo usando docker-compose exec, que permite ejecutar comandos específicos en contenedores. En este caso, abrirá el archivo para editar lo siguiente:

      • docker-compose exec app nano .env

      Busque el bloque que especifica DB_CONNECTION y actualícelo para reflejar los detalles de su configuración. Cambiará los siguientes campos:

      • DB_HOST será su contenedor de base de datos db.
      • `DB_DATABASE será la base de datos laravel.
      • `DB_USERNAME será el nombre de usuario que usará para su base de datos. En este caso, usaremos laraveluser.
      • DB_PASSWORD será la contraseña segura que desee utilizar para esta cuenta de usuario.

      /var/www/.env

      DB_CONNECTION=mysql
      DB_HOST=db
      DB_PORT=3306
      DB_DATABASE=laravel
      DB_USERNAME=laraveluser
      DB_PASSWORD=your_laravel_db_password
      

      Guarde sus cambios y cierre el editor.

      A continuación, establezca la clave de aplicación para la aplicación de Laravel con el comando php artisan key:generate. Este comando generará una clave, dispondrá una copia de esta en su archivo .env y se asegurará de que las sesiones y los datos cifrados de sus usuarios permanezcan seguros:

      • docker-compose exec app php artisan key:generate

      Con esto, dispondrá de los ajustes de entorno necesarios para ejecutar su aplicación. Para almacenar en caché estos ajustes en un archivo, lo cual aumentará la velocidad de carga de su aplicación, ejecute lo siguiente:

      • docker-compose exec app php artisan config:cache

      Sus ajustes de configuración se cargarán en /var/www/bootstrap/cache/config.php en el contenedor.

      Como paso final, visite http://your_server_ip en el navegador. Verá la siguiente página de inicio para su aplicación Laravel:

      Página de inicio de Laravel

      Con sus contenedores en ejecución y la información de su configuración lista, podrá configurar la información de usuario para la base de datos laravel en el contenedor db.

      Paso 9: Crear un usuario para MySQL

      La instalación predeterminada de MySQL solo crea la cuenta administrativa root, que tiene privilegios ilimitados en el servidor de base de datos. Por lo general, es mejor evitar el uso de la cuenta administrativa root al interactuar con la base de datos. En su lugar, crearemos un usuario de base de datos dedicado para la base de datos de nuestra aplicación de Laravel.

      Para crear un nuevo usuario, ejecute un shell bash interactivo en el contenedor db con docker-compose exec:

      • docker-compose exec db bash

      Dentro del contenedor, inicie sesión en la cuenta administrativa root de MySQL:

      Se le solicitará la contraseña que estableció para la cuenta root de MySQL durante la instalación en su archivo docker-compose.

      Comience revisando la base de datos llamada laravel, que definió en su archivo docker-compose. Ejecute el comando show databases para verificar las bases de datos existentes:”“”

      Verá la base de datos laravel en el resultado:“

      Output

      +--------------------+ | Database | +--------------------+ | information_schema | | laravel | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec)

      A continuación, cree la cuenta de usuario que tendrá permisos de acceso a esta base de datos. Nuestro nombre de usuario será laraveluser, aunque puede cambiarlo por otro que prefiera. Asegúrese de que su nombre de usuario y contraseña aquí coincidan con la información que estableció en su archivo .env en el paso anterior:”“

      • GRANT ALL ON laravel.* TO 'laraveluser'@'%' IDENTIFIED BY 'your_laravel_db_password';

      Elimine los privilegios para notificar los cambios al servidor MySQL:

      Cierre MySQL:

      Por último, cierre el contenedor:

      Con esto, habrá configurado la cuenta de usuario para la base de datos de su aplicación de Laravel y estará listo para migrar sus datos y trabajar con la consola Tinker.

      Paso 10: Migrar datos y trabajar con la consola Tinker

      Con su aplicación en ejecución, podrá migrar sus datos y experimentar con el comando tinker, que iniciará una consola PsySH con Laravel precargada. PsySH es una consola para desarrolladores de tiempo de ejecución y un depurador interactivo para PHP, y Tinker es un REPL específico para Laravel. Usar el comando tinker le permitirá interactuar con su aplicación de Laravel desde la línea de comandos en un shell interactivo.

      Primero, pruebe la conexión con MySQL ejecutando el comando Laravel artisan migrate, que crea una tabla migrations en la base de datos dentro del contenedor:

      • docker-compose exec app php artisan migrate

      Con este comando se migrarán las tablas predeterminadas de Laravel. El resultado que confirme la migración tendrá este aspecto:

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table

      Una vez que la migración esté completa, podrá ejecutar una consulta para verificar si su conexión a la base de datos es correcta usando el comando tinker:

      • docker-compose exec app php artisan tinker

      Pruebe la conexión de MySQL obteniendo los datos que acaba de migrar:

      • DB::table('migrations')->get();

      Verá un resultado similar a este:

      Output

      => IlluminateSupportCollection {#2856 all: [ {#2862 +"id": 1, +"migration": "2014_10_12_000000_create_users_table", +"batch": 1, }, {#2865 +"id": 2, +"migration": "2014_10_12_100000_create_password_resets_table", +"batch": 1, }, ], }

      Puede usar tinker para interactuar con sus bases de datos y experimentar con servicios y modelos.

      Una vez implementada su aplicación de Laravel, estará listo para seguir adelante con el desarrollo y la experimentación.

      Conclusión

      Con esto, dispondrá de una aplicación de pila LEMP en ejecución en su servidor, que probó accediendo a la página de bienvenida de Laravel y creando migraciones de base de datos de MySQL.

      La clave de la simplicidad en esta instalación es Docker Compose, que le permite crear un grupo de contenedores de Docker definidos en un solo archivo mediante un comando. Si desea obtener más información sobre cómo realizar una integración continua con Docker Compose, consulte Cómo configurar un entorno de prueba de integración continua con Docker y Docker Compose en Ubuntu 16.04. Si desea simplificar su proceso de implementación de la aplicación de Laravel, resultará pertinente el recurso Cómo implementar de forma automática aplicaciones de Laravel con Deployer en Ubuntu 16.04.



      Source link