Así que acabo de crear una aplicación Node muy básica. Quiero practicar ponerlo en un contenedor acoplable e implementarlo en otro servidor

Estoy usando los pasos aquí (https://nodejs.org/en/ docs / guides / nodejs-docker-webapp /) para crear un dockerfile que construya una imagen de docker.

Quiero tomar esta imagen y copiarla al servidor.

Así que estoy ejecutando este comando para guardarlo en un archivo tar que copiaría al servidor.

docker save -o <save image to path> <image name>

Al ejecutar ese comando, mi imagen tiene un tamaño de 750Mbs, esto es para una aplicación de nodo hello world.

Así que entiendo por qué este es el caso: que 750Mb es para todas las capas descritas en el dockerfile, incluye node: 8, que básicamente contiene el sistema operativo para ejecutar Node.

Mi pregunta es, 750mb es un archivo muy grande cada vez que quiero hacer una implementación. ¿Es posible decirle a Docker cuando se ejecuta el comando SAVE que no empaquete todas las capas? Preferiblemente, solo debería empaquetar mis archivos personalizados para mi aplicación más el dockerfile y generaría la imagen en el servidor.

EDITAR - mi archivo acoplable

FROM node:8

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install
# If you are building your code for production
# RUN npm install --only=production


# Bundle app source
COPY . .

CMD [ "node", "app.js" ]
5
Diskdrive 10 sep. 2018 a las 17:03

3 respuestas

La mejor respuesta

Tomé uno de mis proyectos actuales y básicamente ejecuté su Dockerfile ... y obtuve un archivo tar de 1.1 GB docker save. Se comprime bien, pero un archivo tar comprimido de 345 MB todavía no es lo que buscas. "Usar una imagen base alpina" es algo útil, pero no una bala de plata; cambiarlo a FROM node:8-alpine lo reduce a un archivo tar sin comprimir de 514 MB.

Si aún no tiene un archivo .dockerignore, todo el directorio node_modules existente se copiará en la imagen. (En particular, el paso COPY . . copiará todo su árbol de trabajo, sobrescribiendo los módulos instalados del paso anterior). Puede contener una sola línea

node_modules

La imagen base de Alpine, además de no emitir un árbol duplicado node_modules, me reduce a 382 MB sin comprimir.

Observe en su ejemplo que su paso npm install incluye todas las dependencias de desarrollo, así como las dependencias de tiempo de ejecución. Eso puede ser un costo significativo. Si su aplicación no necesita ninguna precompilación (es un JavaScript simple que Node puede ejecutar directamente), entonces puede agregar esa bandera --only=production y será de ayuda.

Si necesita algún nivel de precompilación (Babel, Webpack, Typecript, ...), entonces necesita una compilación de varias etapas. Mi Dockerfile real tiene tres etapas. El primero realiza la compilación y produce un directorio dist con JavaScript ejecutable. El segundo produce el árbol node_modules que necesito en tiempo de ejecución. El tercero (ya que estamos contando bytes aquí) copia solo las partes que realmente necesitamos de las dos primeras etapas.

La suma se ve así:

FROM node:8-alpine AS build
WORKDIR /usr/src/app
# Installing dependencies first can save time on rebuilds
# We do need the full (dev) dependencies here
COPY package.json yarn.lock ./
RUN yarn install
# Then copy in the actual sources we need and build
COPY tsconfig.json ./
COPY src/ ./src/
RUN yarn build

FROM node:8-alpine AS deps
WORKDIR /usr/src/app
# This _only_ builds a runtime node_modules tree.
# We won't need the package.json to actually run the application.
# If you needed developer-oriented tools to do this install they'd
# be isolated to this stage.
COPY package.json yarn.lock ./
RUN yarn install --production

FROM node:8-alpine
WORKDIR /usr/src/app
COPY --from=deps /usr/src/app/node_modules ./node_modules/
COPY --from=build /usr/src/app/dist ./dist/
EXPOSE 3000
CMD ["node", "dist/index.js"]

docker save en esto produce un archivo tar sin comprimir de 108 MB.

Una cosa que notará, si docker save node:8-alpine, es que esa imagen es de 71 MB por sí sola. Cuando docker save se ve obligado a copiar eso cada vez, y cuando docker load lo obtiene, obtendrá una copia distinta cada vez. La única forma de evitar esto es tener un servidor de registro de algún tipo (Docker Hub, una cosa alojada en la nube como Google GCR o AWS ECR, algo que ejecuta usted mismo) y docker push y docker pull a partir de ahí.

Resulta que la imagen node:8 es enorme ; la mitad de su tamaño es una cadena de herramientas C completa (esa sola capa es solo de 320 MB) (intente ejecutar docker history node:8). La imagen de nodo estándar también tiene una variante node:8-slim que todavía está basada en Debian (y tan grande que la imagen alpina) pero mucho más ordenada. Recibo un archivo tar de 221 MB docker save adaptando mi Dockerfile para que se base en esta imagen. (Y de nuevo, si docker pull obtendrás el tiempo de ejecución del Nodo base una vez, pero si docker load lo obtendrás una y otra vez).

20
David Maze 11 sep. 2018 a las 00:42
  • Puede usar un registro para extraer las imágenes, solo debe descargar el diff:

Docker incluye capacidades similares a git para rastrear versiones sucesivas de un contenedor, inspeccionar la diferencia entre versiones, confirmar nuevas versiones, retroceder, etc. El historial también incluye cómo se ensambló un contenedor y quién lo hizo, para que pueda obtener una trazabilidad completa del servidor de producción todo el camino de regreso al desarrollador upstream. Docker también implementa cargas y descargas incrementales, similares a git pull, por lo que las nuevas versiones de un contenedor se pueden transferir solo enviando diferencias. fuente

  • O puede construir su imagen en el servidor de producción, reutilizará la imagen node:8 y solo necesita implementar su código.

Esta solución tiene limitaciones, ya que puede llevar mucho tiempo construirla, especialmente si se ejecuta en un servidor pequeño.

0
Gabriel Bleu 11 sep. 2018 a las 08:35

Puede usar su propio servicio de registro basado en Docker usando la imagen registry:2. Hospédelo en algún lugar donde desee que la imagen se autentique y actualice y extráigala como desee.

0
sao 2 abr. 2020 a las 15:11