Como se puede entender a partir del artículo anterior, he trabajado en diferentes proyectos. Los primeros días en un nuevo equipo suelen ser similares: el desarrollador de backend se une a mí y realiza acciones mágicas para instalar y desplegar la aplicación. Docker es indispensable para los frontend, ya que el backend a menudo está escrito en una amplia variedad de pilas PHP/Java/Python/C# y el frontend no necesita molestar al backend cada vez para instalar y desplegar. Solo en un lugar he visto una combinación de Docker-Jenkins con despliegue transparente, registros y pruebas automatizadas integradas.
Se han escrito muchos artículos detallados sobre Docker. En este artículo se tratará del despliegue de una Single Page Application utilizando VueJS/Vue Router, con la parte del servidor en forma de RESTful API con NodeJS, y MongoDB como base de datos. Se utiliza Docker Compose para describir y lanzar varios contenedores de aplicaciones.
¿Para qué sirve Docker?
Docker permite automatizar el proceso de despliegue de aplicaciones. Ya no es necesario que el desarrollador instale programas por su cuenta ni que luche con incompatibilidades de versiones en su máquina. Solo hay que instalar Docker y teclear 1-2 comandos en la consola. Es más conveniente hacerlo en Linux.
Empezando
Instalamos y
Estructura de carpetas
Creamos 2 carpetas para las aplicaciones del cliente y del servidor. Un archivo con extensión .yml es un archivo de configuración Docker Compose, donde se definen y enlazan los contenedores de la aplicación.
Docker-compose.yml:
version: "3"
services:
mongo:
container_name: mongo
hostname: mongo
image: mongo
ports:
- "27017:27017"
server:
build: server/
#command: node ./server.js #aquí se puede sobrescribir el CMD del Dockerfile en /server
ports:
- "3000:3000"
links:
- mongo
client:
build: client/
#command: http-server ./dist #aquí se puede sobrescribir el CMD del Dockerfile en /client
network_mode: host
ports:
- "8089:8089"
depends_on:
- server
Creamos 3 servicios en Docker: para NodeJS, MongoDB y para estáticos en Vue. Para enlazar el cliente con el servidor se ha añadido depends on server. Para enlazar MongoDB con la API del servidor se utiliza links mongo. Server, client, mongo son los nombres de los servicios.
Cliente en VueJS
En la carpeta /client la aplicación está ubicada en VueJS. La aplicación fue creada con . Al construir la imagen, la aplicación del cliente se compila en un conjunto de archivos estáticos en la carpeta /dist. En el Dockerfile se describen las instrucciones para construir la imagen:
FROM node:10
WORKDIR /client
COPY ./package*.json ./
RUN npm install
RUN npm install -g http-server
COPY . .
RUN npm run build
EXPOSE 8081
CMD ["npm", "test:dev"]
Tenga en cuenta que package.json se copia e instala por separado de los otros archivos del proyecto. Esto se hace por rendimiento, para que el contenido de la carpeta /node_modules se almacene en caché durante la reconstrucción. Cada línea de comando se almacena en caché por separado.
Al final, al iniciar el contenedor se ejecuta el comando npm run dev. Este comando se describe en package.json:
"scripts": {
"test:dev": "http-server dist -p 8081 -c 1 --push-state"
}
Para ejecutar archivos de la carpeta /dist, se instala globalmente http-server, y en dev-dependencies el paquete spa-http-server, para que Vue Router funcione correctamente. El flag —push-state redirige a index.html. Se añadió el flag -c con un valor de 1 segundo para http-server no almacenar en caché los scripts. Este es un ejemplo de prueba, en un proyecto real es mejor usar nginx.
En el store de Vuex creamos un campo apiHost: 'http://localhost:3000', donde se especifica el puerto de la API de NodeJS. La parte cliente está lista. Ahora todas las solicitudes del cliente al backend van a esta url.
API del servidor NodeJS
En la carpeta /server creamos server.js y Dockerfile:
FROM node:10
WORKDIR /server
COPY ./package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
En server.js se indica url para la base de datos const url = 'mongodb://mongo:27017/';. Permitimos solicitudes cruzadas desde el cliente:
const clientUrl = 'http://localhost:8081';
const corsOptions = {
origin: clientUrl,
optionsSuccessStatus: 200, \\ algunos navegadores heredados (IE11, varios SmartTVs) tienen problemas con 204
};
app.use(cors());
app.all('/*', (req, res, next) => {
res.header('Access-Control-Allow-Origin', clientUrl);
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
next();
});
app.get('/getProducts', cors(corsOptions), (req, res) => {
products.getContent
.then(data => res.json(data), err => res.json(err));
});
app.get('/getUsers', cors(corsOptions), (req, res) => {
db.getUsers()
.then(data => res.json(data), err => res.json(err));
});
Conclusión
Ahora pasemos al directorio del proyecto y ejecutemos docker-compose build para construir las imágenes y docker-compose up para iniciar los contenedores. Este comando levantará 3 contenedores: server, client, mongo. Para el servidor en NodeJS se puede configurar hot-reload, vinculándolo con la carpeta user. Y el cliente en desarrollo se puede ejecutar localmente con hot reload, iniciándolo por separado servidor y mongo. Para iniciar un servicio separado, simplemente indica su nombre docker-compose up client. No olvides hacer de vez en cuando prune y eliminar contenedores (containers), redes (networks) e imágenes (images) para liberar recursos.
El código completo se puede ver . El proyecto aún está en desarrollo.
Fuente: habr.com
