node.js - ¿Cómo ejecuto TypeScript `tsc` antes de `COPY` en Dockerfile.template?
Tengo una solución funcional para construir una aplicación Node en TypeScript al desplegar en Docker mediante el archivo Dockerfile.template:
Thanks: https://github.com/balenalabs/multicontainer-getting-started
FROM balenalib/%%BALENA_MACHINE_NAME%%-node
Defines our working directory in container
WORKDIR /usr/src/app
Install packages
RUN install_packages build-essential libraspberrypi-bin
Copies the package.json first for better cache on later pushes
COPY package.json package.json
Install npm dependencies on the balena.io build server,
making sure to clean up the artifacts it creates in order to reduce the image size.
#NOTE: I removed --production option because I need to run tsc after COPY..., so larger image size remains for now.
RUN JOBS=MAX npm i
This will copy all files in our root to the working directory in the container
COPY . ./
Build from TypeScript
TODO: This feels messy. How may I run `npm i --production` followed by `tsc` before copying files in Docker?
Best answer so far for the next line: https://stackoverflow.com/questions/51083134/how-to-compile-typescript-in-dockerfile
RUN ./node_modules/typescript/bin/tsc -p ./tsconfig.json
server.js will run when container starts up on the device
in package.json: "serve": "node dist/server.js"
CMD ["npm", "run", "serve"]
Preferiría ejecutar tsc antes de copiar los archivos al directorio de la aplicación. Además, ejecutar npm i --production para no tener que incluir dependencias de desarrollo en la aplicación. Sin embargo, esto no parece funcionar después de un npm i -g typescript (antes del COPY), sin que se encuentre un comando. ¿Cuál es la mejor manera de proceder?
Actualizar con solución
Con la solución elegida, aquí hay un script actualizado que funciona para la siguiente persona que busque esto:
###################################
First Stage: Compile TypeScript #
###################################
Thanks: https://stackoverflow.com/questions/60916271/how-do-i-run-typescript-tsc-before-copy-in-dockerfile-template/60917273#60917273
FROM balenalib/%%BALENA_MACHINE_NAME%%-node AS build
Install needed packages to build raspicam Node dependencies.
RUN install_packages build-essential libraspberrypi-bin
WORKDIR /usr/src/app
Install the Javascript dependencies, including all devDependencies.
COPY package.json .
RUN npm i
Copy the rest of the application in and build it.
COPY . ./
RUN TypeScript build
RUN ./node_modules/typescript/bin/tsc -p ./tsconfig.json
Clean up node_modules to not include dev dependencies.
RUN rm -rf ./node_modules
RUN JOBS=MAX npm i --production
##################################
Second Stage: Prepare Dist App #
##################################
FROM balenalib/%%BALENA_MACHINE_NAME%%-node
Defines our working directory in container
WORKDIR /usr/src/app
Install packages
RUN install_packages build-essential libraspberrypi-bin
This will copy all files in our root to the working directory in the container
COPY --from=build /usr/src/app/dist dist
COPY package.json package.json
server.js will run when container starts up on the device
CMD ["npm", "run", "serve"]
Respuesta #1
Puede usar una compilación en varias etapas para esto. La primera etapa incluye todas las dependencias de desarrollo, incluyendo tsc; la segunda etapa solo incluye los archivos que se necesitan para ejecutar la aplicación construida.
(No estoy familiarizado con el entorno de compilación específico que estás usando, así que esto será en términos de la imagen estándar node.)
First stage: compile things.
FROM node:12 AS build
WORKDIR /usr/src/app
(Install OS dependencies; include -dev packages if needed.)
Install the Javascript dependencies, including all devDependencies.
COPY package.json .
RUN npm install
Copy the rest of the application in and build it.
COPY . .
RUN npm build
RUN npx tsc -p ./tsconfig.json
Now /usr/src/app/dist has the built files.
Second stage: run things.
FROM node:12
WORKDIR /usr/src/app
(Install OS dependencies; just libraries.)
Install the Javascript dependencies, only runtime libraries.
COPY package.json .
RUN npm install --production
Copy the dist tree from the first stage.
COPY --from=build /usr/src/app/dist dist
Run the built application when the container starts.
EXPOSE 3000
CMD ["npm", "run", "serve"]
