Escribí mis primeros sitios a finales de los 90. Entonces, ponerlos en funcionamiento era muy sencillo. Había un servidor Apache en algún hosting compartido, al que se podía acceder por FTP, escribiendo en la barra del navegador algo así como ftp://ftp.example.com. Después había que introducir un nombre y una contraseña y subir los archivos al servidor. Eran otros tiempos, todo era más sencillo que ahora.
En las dos décadas transcurridas desde entonces, todo ha cambiado bastante. Los sitios se han vuelto más complejos, y antes de lanzarlos a producción, requieren un proceso de ensamblaje. Un único servidor se ha convertido en múltiples servidores, que operan detrás de balanceadores de carga, y es común utilizar sistemas de control de versiones.
Para mi proyecto personal, tenía una configuración especial. Y sabía que necesitaba poder desplegar el sitio en producción con un solo paso: enviar el código a la rama master en GitHub. Además, sabía que no quería gestionar un enorme clúster de Kubernetes, ni utilizar Docker Swarm, ni mantener un parque de servidores con pods, agentes y toda esa complejidad. Para lograr el objetivo de simplificar al máximo el trabajo, necesitaba familiarizarme con CI/CD.
Si tienes un pequeño proyecto (en este caso se trata de un proyecto de Node.js) y quieres aprender a automatizar el despliegue de este proyecto, garantizando que lo que se almacena en el repositorio coincide exactamente con lo que funciona en producción, entonces creo que este artículo te puede interesar.
Requisitos previos
Se espera que el lector de este artículo tenga conocimientos básicos sobre el uso de la línea de comandos y la escritura de scripts en Bash. Además, necesitará cuentas y .
Objetivos
No diré que este artículo pueda ser considerado un "manual de instrucciones" sin reservas. Más bien, es un documento en el que relato lo que he aprendido y describo el proceso de testing y despliegue de código en producción que he desarrollado, realizado en una sola pasada automatizada.
Así es como ha quedado mi flujo de trabajo.
Para el código enviado a cualquier rama del repositorio, excepto master, se realizan las siguientes acciones:
- Se inicia la construcción del proyecto en Travis CI.
- Se realizan todas las pruebas modulares, de integración y de extremo a extremo.
Solo para el código que entra en master, se realiza lo siguiente:
- Todo lo mencionado anteriormente, más…
- Construcción de la imagen de Docker en base al código actual, configuraciones y entorno.
- Publicación de la imagen en Docker Hub.
- Conexión al servidor de producción.
- Descarga de la imagen desde Docker Hub al servidor.
- Detención del contenedor actual y lanzamiento de uno nuevo basado en la nueva imagen.
Si no sabes nada sobre Docker, imágenes y contenedores, no te preocupes. Te contaré todo sobre eso.
¿Qué es CI/CD?
La abreviatura CI/CD se traduce como ‘integración continua/despliegue continuo’.
▍Integración continua
La integración continua es un proceso en el que los desarrolladores hacen commits en el repositorio principal del código fuente del proyecto (generalmente en la rama master). La calidad del código se asegura mediante pruebas automatizadas.
▍Despliegue continuo
El despliegue continuo es un lanzamiento automatizado de código en producción de manera frecuente. La segunda parte de la abreviatura CI/CD a veces se entiende como ‘entrega continua’. Esto es, en general, lo mismo que el ‘despliegue continuo’, pero ‘entrega continua’ implica la necesidad de una confirmación manual de los cambios antes de iniciar el proceso de despliegue del proyecto.
Inicio
La aplicación con la que aprendí todo esto se llama . Este es un proyecto web en el que estoy trabajando, destinado a tomar notas. Al principio intenté hacer un , o simplemente una aplicación frontend sin servidor, para aprovechar las capacidades estándar de alojamiento y despliegue que ofrece . A medida que aumentaba la complejidad de la aplicación, necesitaba crear su parte del servidor, lo que significaba que tenía que formular mi propia estrategia de integración y despliegue automatizados del proyecto.
En mi caso, la aplicación consiste en un servidor Express, que funciona en el entorno Node.js, que sirve una aplicación React de una sola página y soporta una API de servidor segura. Esta arquitectura sigue una estrategia que se puede encontrar en guía sobre la autenticación full stack.
Consulté a , que es un experto en automatización, y le pregunté qué necesitaba hacer para que todo funcionara como yo quería. Él me dio una idea de cómo debería ser el flujo de trabajo automatizado descrito en la sección 'Objetivos' de este artículo. El hecho de que me haya propuesto tales objetivos significaba que necesitaba entender cómo usar Docker.
Docker
Docker es una herramienta que, gracias a la tecnología de contenedorización, permite distribuir aplicaciones fácilmente, así como desplegarlas y ejecutarlas en el mismo entorno, incluso si la propia plataforma Docker funciona en diferentes entornos. Primero, necesitaba tener acceso a las herramientas de línea de comandos (CLI) de Docker. para instalar Docker no se pueden considerar muy claras y comprensibles, pero de ellas se puede aprender que, para dar el primer paso en la instalación, es necesario descargar Docker Desktop (para Mac o Windows).
Docker Hub es algo similar a para los repositorios git, o un registro para paquetes de JavaScript. Es un repositorio en línea para imágenes de Docker. Docker Desktop se conecta a él.
Así que, para empezar a trabajar con Docker, hay que hacer dos cosas:
- Instala .
- Regístrate en .
Después de esto, puedes comprobar el funcionamiento de Docker CLI ejecutando el siguiente comando para verificar la versión de Docker:
docker -vLuego, inicia sesión en Docker Hub ingresando, cuando se te pida, tu nombre de usuario y contraseña:
docker loginPara usar Docker, debes entender los conceptos de imágenes y contenedores.
▍Imágenes
Una imagen es como un plano que contiene instrucciones para construir un contenedor. Es una instantánea inmutable del sistema de archivos y la configuración de la aplicación. Los desarrolladores pueden intercambiar imágenes con facilidad.
# Вывод сведений обо всех образах
docker imagesEste comando mostrará una tabla con el siguiente encabezado:
REPOSITORY TAG IMAGE ID CREATED SIZE
---A continuación, veremos algunos ejemplos de comandos en el mismo formato: primero va el comando con un comentario, y luego un ejemplo de lo que puede mostrar.
▍Contenedores
Un contenedor es un paquete ejecutable que contiene todo lo necesario para ejecutar una aplicación. Con este enfoque, la aplicación siempre funcionará de la misma manera, independientemente de la infraestructura: en un entorno aislado y en el mismo tipo de entorno. Se trata de que se ejecutan instancias de la misma imagen en diferentes entornos.
# Перечисление всех контейнеров
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
---▍Etiquetas
Una etiqueta es una referencia a una versión específica de la imagen.
▍Breve referencia de comandos de Docker
Aquí hay un resumen de algunos de los comandos de Docker más utilizados.
Comando
Contexto
Acción
Imagen
Construir una imagen a partir de un Dockerfile
Imagen
Etiquetar la imagen
Imagen
Mostrar lista de imágenes
Contenedor
Ejecutar un contenedor basado en la imagen
Imagen
Enviar la imagen al registro
Imagen
Descargar la imagen del registro
Contenedor
Mostrar lista de contenedores
Imagen/Contenedor
Eliminar contenedores e imágenes no utilizados
▍Archivo Dockerfile
Sé cómo ejecutar localmente una aplicación para producción. Tengo una configuración de Webpack diseñada para construir una aplicación React lista. Además, tengo un comando que inicia un servidor basado en Node.js en el puerto 5000. Así es como se ve:
npm i # instalar dependencias
npm run build # construir la aplicación React
npm run start # iniciar el servidor NodeCabe destacar que no tengo una aplicación de ejemplo para este material. Pero para experimentos, cualquier aplicación Node sencilla funcionará.
Para utilizar el contenedor, necesitarás dar instrucciones a Docker. Esto se hace a través de un archivo llamado Dockerfile, que se encuentra en el directorio raíz del proyecto. Este archivo, al principio, puede parecer bastante confuso.
Pero lo que contiene es simplemente una descripción, utilizando comandos específicos, de algo similar a la configuración de un entorno de trabajo. Aquí algunos de estos comandos:
- — Este comando inicia el archivo. Se especifica la imagen base a partir de la cual se construye el contenedor.
- — Copiar archivos de una fuente local al contenedor.
- — Establecer el directorio de trabajo para los siguientes comandos.
- — Ejecutar comandos.
- — Configurar el puerto.
- — Especificar el comando a ejecutar.
Dockerfile puede verse algo así:
# Загрузить базовый образ
FROM node:12-alpine
# Скопировать файлы из текущей директории в директорию app/
COPY . app/
# Использовать app/ в роли рабочей директории
WORKDIR app/
# Установить зависимости (команда npm ci похожа npm i, но используется для автоматизированных сборок)
RUN npm ci --only-production
# Собрать клиентское React-приложение для продакшна
RUN npm run build
# Прослушивать указанный порт
EXPOSE 5000
# Запустить Node-сервер
ENTRYPOINT npm run startDependiendo de la imagen base seleccionada, puede que necesite instalar dependencias adicionales. Esto se debe a que algunas imágenes base (como Node Alpine Linux) están diseñadas para ser lo más compactas posible. Como resultado, pueden faltar algunos programas en los que confía.
▍Construcción, etiquetado y ejecución del contenedor
La construcción y ejecución local del contenedor son, después de que tengamos Dockerfile, tareas bastante sencillas. Antes de enviar la imagen a Docker Hub, debe ser probada localmente.
▍Construcción
Primero debe construirse , especificando un nombre y, opcionalmente, una etiqueta (si no se especifica una etiqueta, el sistema asignará automáticamente una etiqueta a la imagen latest).
# Сборка образа
docker build -t <image>:<tag> .Después de ejecutar este comando, puede observar cómo Docker lleva a cabo la construcción de la imagen.
Enviando contexto de construcción al demonio de Docker 2.88MB
Paso 1/9 : FROM node:12-alpine
---> ...ejecución de las etapas de construcción...
Construido con éxito 123456789123
Etiquetado correctamente <imagen>:<etiqueta> La construcción puede tardar un par de minutos, depende de cuántas dependencias tenga. Una vez finalizada la construcción, puede ejecutar el comando docker images y echar un vistazo a la descripción de su nueva imagen.
REPOSITORIO ETIQUETA ID DE IMAGEN CREADO TAMAÑO
<imagen> última 123456789123 Hace aproximadamente un minuto x.xxGB▍Ejecución
La imagen ha sido creada. Esto significa que se puede ejecutar un contenedor basado en ella. Debido a que quiero tener la capacidad de acceder a la aplicación que está funcionando en el contenedor en la dirección localhost:5000, he establecido en la parte izquierda del par 5000:5000 en el siguiente comando. 5000. En la parte derecha está el puerto del contenedor.
# Запуск с использованием локального порта 5000 и порта контейнера 5000
docker run -p 5000:5000 <image>:<tag> Ahora, cuando el contenedor ha sido creado y está en ejecución, puede usar el comando docker ps para ver la información sobre este contenedor (o puede usar el comando docker ps -a, que muestra la información sobre todos los contenedores, no solo los que están en funcionamiento).
ID DEL CONTENEDOR IMAGEN COMANDO CREADO ESTADO PUERTOS NOMBRES
987654321234 <imagen> "\/bin\/sh -c 'npm run…" Hace 6 segundos En funcionamiento desde 6 segundos 0.0.0.0:5000->5000\/tcp stoic_darwin Si ahora accede a la dirección localhost:5000 — puede ver la página de la aplicación en funcionamiento, que se ve exactamente como la página de la aplicación funcionando en un entorno de producción.
▍Asignación de etiqueta y publicación
Para utilizar una de las imágenes creadas en el servidor de producción, necesitamos tener la capacidad de cargar esta imagen desde Docker Hub. Esto significa que primero hay que crear un repositorio en Docker Hub para el proyecto. Después de esto, tendremos un lugar al que podemos enviar la imagen. La imagen debe ser renombrada de tal manera que su nombre comience con nuestro nombre de usuario en Docker Hub. Después de esto debería ir el nombre del repositorio. Al final del nombre puede haber cualquier etiqueta. A continuación se muestra un ejemplo de la nomenclatura de las imágenes según este esquema.
Ahora podemos construir la imagen asignándole un nuevo nombre y ejecutar el comando docker push para enviarla al repositorio de Docker Hub.
docker build -t \/ : .
docker tag \/ : \/ :latest
docker push \/ :
# En práctica, esto podría verse así:
docker build -t user\/app:v1.0.0 .
docker tag user\/app:v1.0.0 user\/app:latest
docker push user\/app:v1.0.0Si todo va bien, la imagen estará disponible en Docker Hub y será fácil de cargar en el servidor o de pasar a otros desarrolladores.
Próximos pasos
Hasta este momento, nos hemos asegurado de que la aplicación, en forma de contenedor Docker, funciona localmente. Hemos cargado el contenedor en Docker Hub. Todo esto significa que ya hemos avanzado bastante hacia nuestro objetivo. Ahora debemos resolver dos preguntas más:
- Configuración de la herramienta CI para pruebas y despliegue del código.
- Configuración del servidor de producción para que pueda cargar y ejecutar nuestro código.
En nuestro caso, estamos utilizando como solución CI/CD . Como servidor — .
Es importante mencionar que aquí se puede utilizar otra combinación de servicios. Por ejemplo, en lugar de Travis CI, se puede utilizar CircleCI o Github Actions. Y en lugar de DigitalOcean, AWS o Linode.
Decidimos trabajar con Travis CI, y en este servicio ya tengo algunas configuraciones hechas. Así que ahora brevemente contaré cómo prepararlo para que funcione.
Travis CI
Travis CI es una herramienta para pruebas y despliegue de código. No me gustaría entrar en los detalles de la configuración de Travis CI, ya que cada proyecto es único y esto no ofrecería un beneficio particular. Pero hablaré sobre lo básico que te permitirá comenzar a trabajar en caso de que decidas utilizar Travis CI. Independientemente de lo que elijas — Travis CI, CircleCI, Jenkins, o algo más — se aplicarán métodos de configuración similares.
Para empezar a trabajar con Travis CI, dirígete a y crea una cuenta. Luego, integra Travis CI con tu cuenta de GitHub. Durante la configuración del sistema, deberás especificar el repositorio con el que deseas automatizar el trabajo y habilitar el acceso a él. (Utilizo GitHub, pero estoy segura de que Travis CI también puede integrarse con BitBucket, GitLab y otros servicios similares).
Cada vez que Travis CI comienza a trabajar, se inicia un servidor que ejecuta los comandos especificados en el archivo de configuración, incluyendo el despliegue de las ramas correspondientes del repositorio.
▍Ciclo de vida del trabajo
El archivo de configuración de Travis CI, llamado .travis.yml y que se almacena en el directorio raíz del proyecto, soporta la concepción de eventos del trabajo. Estos son los eventos, presentados en el orden en que ocurren:
apt addonscache componentsbefore_installinstallbefore_scriptscriptbefore_cacheafter_success o after_failurebefore_deploydeployafter_deployafter_script
▍Pruebas
En el archivo de configuración, voy a configurar un servidor local de Travis CI. He elegido Node en versión 12 y le he indicado al sistema que debe instalar las dependencias necesarias para usar Docker.
Todo lo que se enumera en .travis.yml, se ejecutará para cada pull request a todas las ramas del repositorio, a menos que se indique lo contrario. Esta es una característica útil, ya que significa que podemos probar todo el código que entra al repositorio. Esto permite saber si el código está listo para ser escrito en la rama master, y si no romperá el proceso de construcción del proyecto. En esta configuración global, instalo todo localmente, inicio el servidor de desarrollo de Webpack en segundo plano (esta es una característica de mi flujo de trabajo) y ejecuto las pruebas.
Si deseas que se muestren insignias en tu repositorio con información sobre la cobertura de código, puedes encontrar una breve guía sobre cómo usar Jest, Travis CI y Coveralls para recopilar y mostrar esta información.
Así que aquí está el contenido del archivo .travis.yml:
# Установить язык
language: node_js
# Установить версию Node.js
node_js:
- '12'
services:
# Использовать командную строку Docker
- docker
install:
# Установить зависимости для тестов
- npm ci
before_script:
# Запустить сервер и клиент для тестов
- npm run dev &
script:
# Запустить тесты
- npm run testAquí terminan las acciones que se llevan a cabo para todas las ramas del repositorio y para los pull requests.
▍Despliegue
Partiendo de la suposición de que todas las pruebas automatizadas se completaron con éxito, podemos, aunque no es necesario, desplegar el código en el servidor de producción. Dado que queremos hacer esto solo para el código de la rama master, le damos a la sistema las instrucciones adecuadas en la configuración de implementación. Antes de que intentes usar en tu proyecto el código que revisaremos a continuación, me gustaría advertirte que debes tener un script real que se llame para la implementación.
deploy:
# Compilar el contenedor Docker y enviarlo a Docker Hub
provider: script
script: bash deploy.sh
on:
branch: masterEl script de implementación cumple dos funciones:
- Compilación, etiquetado y envío de la imagen a Docker Hub utilizando herramientas de CI (en nuestro caso, se trata de Travis CI).
- Descarga de la imagen en el servidor, detención del contenedor antiguo y lanzamiento del nuevo (en nuestro caso, el servidor funciona en la plataforma DigitalOcean).
Primero, es necesario configurar el proceso automático de compilación, etiquetado y envío de la imagen a Docker Hub. Todo esto es muy similar a lo que ya hacíamos manualmente, excepto que aquí necesitamos una estrategia para asignar etiquetas únicas a las imágenes y automatizar el inicio de sesión. Tuve dificultades con algunos detalles del script de implementación, como la estrategia de etiquetado, el inicio de sesión, la codificación de las claves SSH y el establecimiento de la conexión SSH. Pero, afortunadamente, mi novio maneja muy bien bash, al igual que muchas otras cosas. Él me ayudó a escribir este script.
Entonces, la primera parte del script es enviar la imagen a Docker Hub. Hacer esto es bastante simple. El esquema de etiquetado que utilicé implica combinar el hash de git y el tag de git, si existe. Esto permite garantizar la creación de una etiqueta única y simplifica la identificación de la compilación de la que se basa. DOCKER_USERNAME y DOCKER_PASSWORD son variables de entorno personalizadas que se pueden establecer a través de la interfaz de Travis CI. Travis CI manejará automáticamente los datos secretos para que no caigan en manos ajenas.
Aquí está la primera parte del script deploy.sh.
#!/bin/sh
set -e # Остановить скрипт при наличии ошибок
IMAGE="<username>/<repository>" # Образ Docker
GIT_VERSION=$(git describe --always --abbrev --tags --long) # Git-хэш и теги
# Сборка и тегирование образа
docker build -t ${IMAGE}:${GIT_VERSION} .
docker tag ${IMAGE}:${GIT_VERSION} ${IMAGE}:latest
# Вход в Docker Hub и выгрузка образа
echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USERNAME}" --password-stdin
docker push ${IMAGE}:${GIT_VERSION} Qué será la segunda parte del script depende completamente de qué hosting estés utilizando y cómo está organizada la conexión. En mi caso, ya que uso Digital Ocean, se utilizan los comandos para conectarse al servidor . Al trabajar con Aws, se utilizará la utilería aws, y así sucesivamente.
No fue especialmente difícil configurar el funcionamiento del servidor. Así, configuré un droplet basado en una imagen básica. Cabe destacar que el sistema que elegí requiere una instalación manual de Docker una sola vez y un inicio manual de Docker una sola vez. Para instalar Docker, utilicé Ubuntu 18.04, por lo que si también utilizas Ubuntu para hacer lo mismo, puedes simplemente seguir una guía sencilla.
No estoy hablando aquí de comandos específicos para el servicio, ya que este aspecto puede variar mucho entre diferentes casos. Solo proporcionaré un plan de acción general que se lleva a cabo después de conectarse por SSH al servidor donde se desplegará el proyecto:
- Hay que encontrar el contenedor que se está ejecutando actualmente y detenerlo.
- Luego, se debe iniciar un nuevo contenedor en segundo plano.
- Necesitarás configurar el puerto local del servidor en el valor
80— lo que permitirá acceder al sitio web en una dirección comoexample.com, sin necesidad de especificar el puerto, en lugar de usar una dirección comoexample.com:5000. - Y, por último, hay que eliminar todos los contenedores y las imágenes antiguas.
Aquí está la continuación del script.
# Найти ID работающего контейнера
CONTAINER_ID=$(docker ps | grep takenote | cut -d" " -f1)
# Остановить старый контейнер, запустить новый, очистить систему
docker stop ${CONTAINER_ID}
docker run --restart unless-stopped -d -p 80:5000 ${IMAGE}:${GIT_VERSION}
docker system prune -a -fAlgunas cosas a tener en cuenta
Es posible que, cuando te conectes al servidor por SSH desde Travis CI, veas una advertencia que impedirá continuar con la instalación, ya que el sistema esperará una respuesta del usuario.
La autenticidad del host '<hostname> (<IP address>)' no puede ser establecida.
La huella digital de la clave RSA es <key fingerprint>.
¿Estás seguro de que quieres continuar conectándote (sí/no)? Descubrí que la clave en texto plano se puede codificar en base64 para poder guardarla en un formato que se pueda manejar de manera conveniente y segura. En la etapa de instalación, se puede decodificar la clave pública y escribirla en el archivo known_hosts para poder deshacerse del error mencionado anteriormente.
echo <public key> | base64 # genera <clave pública codificada en base64>En la práctica, este comando puede verse así:
echo "123.45.67.89 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En
mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx
NrRFi9wrf+M7Q== you@example.com" | base64Y así es como se ve lo que genera: una cadena en codificación base64:
123.45.67.89 ssh-rsa AABAB3NzaC1yc2EAAAAABQiD0AAQ...0M1zWWMz0XNoM2FRQl93AHksNVU3Zjg2eUInTHZ0aVERcGg2SHNhcG5yHzdaJTEJPVdqL0lMQWVpMkFGQmU1OENjdTdmSC9mN2NDOUk1b2N5dlhZNDNNRGFnXkxvcmZUbnpjbHRZYXdSZXMtYV9lYXBjaVZKcExNT0FwaGV4aHE3ZGBlemJKVi82NCtVY1hFZ3Y5QmRjWDNOa2pjN0FOVTlNSUV0b2RWcUVzdzk9Y2Qw...9Cgo==Aquí está el comando mencionado anteriormente
install:
- echo | base64 -d >> $HOME/.ssh/known_hostsEl mismo enfoque se puede usar con la clave privada al establecer una conexión, ya que es posible que necesites la clave privada para acceder al servidor. Al trabajar con la clave, solo necesitas asegurarte de que se almacene de forma segura como una variable de entorno en Travis CI y que no se imprima en ningún lugar.
Otra cosa a tener en cuenta es que es posible que necesites ejecutar todo el script de despliegue presentado como una sola línea, por ejemplo, utilizando doctl. Esto puede requerir algunos esfuerzos adicionales.
doctl compute ssh --ssh-command "todos los comandos estarán aquí && aquí"TLS/SSL y balanceo de carga
Después de hacer todo lo mencionado anteriormente, el último problema que enfrenté fue que el servidor no tenía SSL. Dado que estoy usando un servidor Node.js, para forzar un proxy inverso Nginx y Let's Encrypt, es necesario hacer un buen trabajo.
No quería hacer toda esta configuración de SSL manualmente, así que simplemente creé un balanceador de carga y registré la información en DNS. En el caso de DigitalOcean, por ejemplo, crear un certificado autofirmado auto-renovable en el balanceador de carga es un procedimiento simple, gratuito y rápido. Este enfoque tiene la ventaja adicional de que, si es necesario, permite configurar SSL muy fácilmente en múltiples servidores que trabajan detrás del balanceador de carga. Esto permite que los servidores no tengan que preocuparse por SSL, pero aún así utilicen, como de costumbre, el puerto 80. Así que configurar SSL en el balanceador de carga es mucho más fácil y conveniente que los métodos alternativos de configuración de SSL.
Ahora se pueden cerrar todos los puertos en el servidor que aceptan conexiones entrantes, excepto el puerto 80, utilizado para comunicarse con el balanceador de carga, y el puerto 22 para SSH. Como resultado, intentar acceder directamente al servidor a través de cualquier puerto, excepto estos dos, fallará.
Resultados
Después de haber hecho todo lo que mencioné en este material, ya no tenía miedo ni de la plataforma Docker ni de las concepciones de las cadenas automatizadas de CI/CD. Pude establecer una cadena de integración continua, durante la cual se realiza la prueba del código antes de que llegue a producción y el despliegue automático del código en el servidor. Todo esto es todavía relativamente nuevo para mí, y estoy segura de que hay formas de mejorar mi flujo de trabajo automatizado y hacerlo más eficiente. Así que si tienes ideas al respecto, házmelo saber. Espero que este artículo te haya ayudado en tus asuntos. Quiero creer que al leerlo, aprendiste tanto como yo mientras investigaba todo lo que aquí se menciona.
P.D. En nuestro hay una imagen , que se instala con un solo clic. Puedes comprobar el funcionamiento de los contenedores en . Todos los nuevos clientes tienen 3 días de prueba gratuita.
¡Estimados lectores! ¿Utilizas tecnologías de CI/CD en tus proyectos?
Fuente: habr.com
