Too many intro to Docker tutorials create multiple Dockerfiles for each environment, or only go over creating one environment. Here's a quick and easy way to keep a single file and overwrite the command in development.
Let's look at an example Dockerfile for building a react app and copying it over to nginx:
FROM node:latest COPY package.json package.json COPY package-lock.json package-lock.json RUN npm install COPY . . RUN npm run build --production CMD ./node_modules/.bin/serve -s build EXPOSE 5000
Looks great, right? We copy our package.json and npm install only if those files have changed. Then we add our whole project directory and do a production build. After that we serve the build folder with a little http server module. So easy you probably knew all of this before I explained it. Now let's create a
version: '3' services: web: build: context: . dockerfile: ./Dockerfile command: ./node_modules/.bin/webpack-dev-server --hot --inline --config config/dev.config.js image: web ports: - 8080:8080 volumes: - ./src:/src
Pretty standard compose file! We can pass a custom command here to override the default one. Webpack's dev server by default runs on 8080. Docker compose will let you map a port even if it's not exposed in the Dockerfile, that's why we are able to port map.
You may realize that we are still doing the production build before the dev server command. I think it's a good idea to run other steps that are meant for production. If that step failed, but the dev server worked, you wouldn't know until you did a production build. It's a neccesary trade off, but I can see both sides to this.
Now we have a single Dockerfile for production and development. I understand that some people may have more complex Dockerfiles, in fact some of my own projects are. Keep things simple and single use and it's very easy to use the same one for multiple environments. Let me know if you have any questions below or @zachcodes.