Estoy intentando npm run start una aplicación React que se creó con --template typescript. Por lo tanto, TypeScript está instalado (como una dependencia de React) pero mi contenedor Docker se queja con un mensaje de error genérico de que TypeScript no se instalaría. Por lo tanto, no puedo iniciar la aplicación dentro de un contenedor Docker.

Todo funciona, cuando inicio la aplicación (con el mismo package.json) fuera del contenedor.

Error

> frontend@0.1.0 start /app
> react-scripts start

It looks like you're trying to use TypeScript but do not have typescript installed.
Please install typescript by running npm install typescript.

npm ERR! Exit status 1

Agregué TypeScript a través de npm install typescript y reconstruí el contenedor Docker. Pero todavía muestra el mensaje de error.

Incluso después de agregar typescript manualmente como una dependencia (¡incluso dentro del contenedor con una llamada directa a npm install typescript allí!), El contenedor se quejó de no poder encontrar TypeScript (lo cual no parece ser cierto ya que puedo validar que TypeScript se instaló dentro del contenedor ya que tsc -version me muestra el resultado correcto).

Código

Mi Dockerfile tiene este aspecto:

FROM node:15.4.0-alpine3.12

# set working directory
ARG app_path=/app
WORKDIR ${app_path}

# add `node_modules/.bin` to $PATH
ENV PATH ${app_path}/node_modules/.bin:$PATH

# set Docker port
EXPOSE 3000

# copy configs, no need to copy src files as they get bind mounted later on (see docker-compose)
COPY package*.json ./
COPY tsconfig.json ./

# install all app dependencies
RUN npm install --silent

# validate typescript installation
RUN tsc --version

Mi archivo docker-compose.yaml se ve así:

version: '3.8'
services:
  frontend:
    build:
      context: ./frontend
      dockerfile: ../Dockerfile
    image: frontend:dev
    container_name: dev_frontend_react
    ports:
      - 4000:3000
    command: ['npm', 'run', 'start']
    volumes:
      - ${HOST_PROJECT_PATH}/frontend:/app
      
      # add a virtual volume to overwrite the copied node_modules folder as the
      # container installs its own node_modules
      - node_modules:/app/node_modules
    environment:
      - NODE_ENV=development
    restart: unless-stopped

volumes:
  node_modules:
    name: frontend_node_modules

Misma pregunta, solución que no funciona

Encontré otra solución a la misma pregunta aquí en StackOverflow: Se le solicitó instalar TypeScript cuando ya estaba instalado al compilar Docker imagen

Pero esta solución es hacer una copia impresa del proyecto en el contenedor y crear una compilación real. Pero esa solución no es aceptable para mí, ya que evita que funcione la función de recarga en caliente de React.

0
winklerrr 21 ene. 2021 a las 19:26

1 respuesta

La mejor respuesta

Durante la compilación de la imagen de Docker (es decir, en el Dockerfile), está instalando las dependencias en la carpeta node_modules dentro del contenedor (RUN npm install --silent). Type script (tsc --version) funciona a medida que se instala allí.

Más tarde, en el archivo docker-compose, está reemplazando la carpeta node_modules con una carpeta de la máquina host. Entonces, efectivamente, los comandos del Dockerfile no tienen ningún efecto.

No estoy seguro de cuál es tu objetivo, pero puedo ver varias opciones:

  • si desea que el contenedor de la ventana acoplable instale las dependencias en la carpeta de la máquina host (?), debe hacerlo cuando se inicia el contenedor, no cuando se está compilando la imagen
  • si solo desea usar dependencias de la carpeta del host, asegúrese de que typescript esté allí
  • Si su objetivo es ejecutar la aplicación en la ventana acoplable, pero aún puede editar y volver a cargar la aplicación en caliente, intente montar la carpeta src solo (pero luego no podrá agregar nuevas dependencias)

ACTUALIZACIÓN:

En realidad, su solución debería funcionar. Docker-compose debería copiar archivos de node_modules dentro del contenedor en el volumen montado. Sin embargo, hay un problema: lo hace solo cuando el volumen se crea recientemente (consulte rellenar un volumen usando un contenedor). Entonces, para resolver el problema, intente eliminar el volumen y vuelva a ejecutar la ventana acoplable componer:

docker volume rm frontend_node_modules

Desafortunadamente, debe hacerlo cada vez que haya cambios en las dependencias. Alternativamente, puede utilizar:

docker-compose down -v

Que también eliminará volúmenes (de forma predeterminada, docker-compose down no elimina volúmenes, por lo tanto, el interruptor -v)

2
Mafor 22 ene. 2021 a las 15:41