0

Below is my dockerfile. After the dependencies are installed, I want to delete a specific binary (ffmpeg) from the node_modules folder on the container, and then reinstall it using the install.js file that exists under the same folder in node_modules.

FROM node:16-alpine

WORKDIR /web

COPY package.json package-lock.json ./

ARG NODE_ENV
ENV NODE_ENV ${NODE_ENV:-development}

ARG _ENV
ENV _ENV ${_ENV:-dev}

RUN npm install

RUN rm /web/node_modules/ffmpeg-static/ffmpeg
RUN node /web/node_modules/ffmpeg-static/install.js

COPY . .

EXPOSE 8081
ENTRYPOINT [ "npm" ]

I want the rm and node commands to take effect on the container after the startup and when all the dependencies are installed and copied to the container, but it doesn't happen. I feel like the commands after RUN are only executed during the build process, not after the container starts up.

After the container is up, when I ssh to it and execute the two commands above directly (RUN rm... and RUN node...), my changes are taking effect and everything works perfectly. I basically want these commands to automatically run after the container is up and running.

The docker-compose.yaml file looks like this:

version: '3'
services:
  serverless:
    build: web
    user: root
    ports:
      - '8081:8081'

    env_file:
      - env/web.env
    environment:
      - _ENV=dev
    command:
      - run
      - start
    volumes:
      - './web:/web'
      - './env/mount:/secrets/'

Josh
  • 189
  • 1
  • 16
  • What are you copying with the second copy statement `COPY . .`? Also, I would try combining the two RUNs here. `RUN npm install && rm /web/node_modules/ffmpeg-static/ffmpeg` – Jake Nelson Mar 26 '22 at 04:16
  • That copies the source code to the workdir location (/web). – Josh Mar 26 '22 at 06:27
  • I tried adding the other command next to nom install but no luck. – Josh Mar 26 '22 at 06:27
  • you sure you dont copy the node modules back into the image? – The Fool Mar 26 '22 at 10:23
  • How are you actually running the container; what's in your `docker-compose.yml` file? (In particular, do you have `volumes:` that replace absolutely everything in the image with other content?) – David Maze Mar 26 '22 at 10:50
  • I made some changes to the question. I want two commands (not only the rm command) to run after the container starts up. But it doesn't happen. – Josh Mar 26 '22 at 19:23
  • What you mean by run 2 commands after the container starts? When the container starts, It runs the entrypoint with the args from compose command: `npm run start`. In your Dockerfile, is no command, so the new title of the question doesn't make a lot of sense. You also haven't addressed the question if you copy the file back into the image / mount it with your volumes spec, yet. Does your local folder contain the node_modules folder with the file inside or not? – The Fool Mar 26 '22 at 23:58
  • @TheFool So basically, as soon as the docker starts, the `npm run start` command runs as expected. But I want to run the below commands on the docker as well after the startup: `rm /web/node_modules/ffmpeg-static/ffmpeg` and `node /web/node_modules/ffmpeg-static/install.js` About your last question, yes. The file remains there even locally (before copy), as the command is not running successfully. – Josh Mar 27 '22 at 02:08
  • That's not how it works. The mentioned lines are RUN instructions. Those are run when building the image, not when running a container. You have to make them part of entrypoint or cmd. In your case cmd doesnt work because you have npm as entrypoint. You could also make them part of your npm start script. – The Fool Mar 27 '22 at 08:57
  • The suggestion to add node_modules to .dockerignore in the below answer, seems a good solution for the final image. The RUN instruction is run successfully. You are just adding it back into the image. In your compose, you additionally mount the src folder, including your local node_modules. So even then a .dockerignore doesn't help. For development, it probably doesn't matter and in production you probably don't mount the code, so I would say .dockerignore on node_modules is sufficient. – The Fool Mar 27 '22 at 09:05
  • Well .dockerignore works for the first command (rm) where I delete a file. But the second command is where I run the inatall.js file. Adding these commands too the ‘npm run start’ seems like a good suggestion. I’m going to try that. – Josh Mar 27 '22 at 13:36
  • …and adding the commands to the ‘npm run start’ did the trick. Thanks for the suggestion. If you wanna get a green check post your suggestion. – Josh Mar 27 '22 at 16:19

2 Answers2

1

if this dockerfile builds, it means you have a package-lock.json. That is evidence that npm install was executed in the root directory for that image, which means that node_modules exists locally and is being copied in the last copy.

You can avoid this by creating a .dockerignore file that includes files and directories (aka node_modules) that you'd like to exclude from being passed to the Docker build context, which will make sure that they don't get copied to your final image.

You can follow this example: https://stackoverflow.com/a/43747867/3669093

Update

Dockerfile: Replace the ENTRYPOINT with the following

ADD ./start.sh /start.sh
CMD ["/start.sh"]

Start.sh

rm /web/node_modules/ffmpeg-static/ffmpeg
node /web/node_modules/ffmpeg-static/install.js

npm
  • I made some changes to the question. I want two commands (not only the rm command) to run after the container starts up. But it doesn't happen. – Josh Mar 26 '22 at 19:23
  • @Josh if you'd like to two commands to run at container startup then you actually need them to run at run time not at build time. All the commands you write in the docker file (except CMD and ENTRYPOINT) run at BUILD time, aka. when building the image. – mwalidawadeen Apr 27 '22 at 08:04
0

Try rm -rf /web/node_modules/ffmpeg-static/ffmpeg

I assume that is directory, not a file.