Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Segun Olaiya
Segun Olaiya

Posted on

     

Use same Dockerfile for Dev & Production

In many projects that are containerized, especially in cases where development is also done locally withdocker-compose, teams often have two Dockerfiles, 1 for Development, the other for Production. If you happen to have multiple environments likepre-prod,staging and so on, some teams could have different Dockerfiles for these environments.

docker build has a very nice--target option, that could be used to target a specificstage from the Dockerfile.

Let's take a very simple example: let's say we are trying to build a simple frontend app with npm, on Development, we start the app withnpm run dev but on production, we need to runnpm run generate and then copy the artefacts to Nginx's html folder to run, we would need to have a Dockerfile as below for Development:

FROM node:18-alpineWORKDIR /usr/srcCOPY ./package.json ./RUNnpminstallCOPY . .CMD ["npm", "run", "dev"]EXPOSE 3000
Enter fullscreen modeExit fullscreen mode

This is simply a Dockerfile that starts a frontend app withnpm run dev exposing port 3000.

However, we typically do not runnpm run dev on production, extra steps are required to generate the static files from the application and then these files are served bynginx or any other webserver.

To write the production Dockerfile for this app, we need to build the app and also serve with the desired web server.

Docker Multi-Stage builds

Dockermulti-stage builds allows us to use multipleFROM commands in a single Dockerfile, it allows us to selectively copy files from different stages into another.

For our case, we need a base, dev, build and prod stages, we are going to build our app for production withnpm run generate and we need to serve the built files with nginx. Our production Dockerfile will therefore look like this:

FROMnode:18-alpineASbuildWORKDIR /usr/srcCOPY ./package.json ./RUNnpminstallCOPY . .RUNnpm run generateFROM nginx:1.25.1-alpineCOPY --from=build /usr/src/dist /usr/share/nginx/htmlEXPOSE 80CMD ["nginx", "-g", "daemon off;"]
Enter fullscreen modeExit fullscreen mode

Notice theAS build on the first stage, all commands before any otherFROM is considered a stage on their own.

After runningnpm run generate in the app, it generates files into/usr/src/dist.

In the second stage, where we are basing that onnginx, we simply copy those files from the build stage using

COPY --from=build /usr/src/dist /usr/share/nginx/html
Enter fullscreen modeExit fullscreen mode

Updating this Dockerfile to serve both Dev and Production

Now that we have seen multi-stage docker builds in action, we can leverage this by having abase stage,build stage and finally aprod stage.

To achieve this we update the docker file to this:

FROMnode:18-alpineasbaseWORKDIR /usr/srcCOPY ./package.json ./RUNnpminstallCOPY . .FROMbaseASdevEXPOSE  3000CMD ["npm", "run", "dev"]FROMbaseASbuildRUNnpm run buildFROMnginx:1.25.1-alpineasprodCOPY --from=build /usr/src/dist /usr/share/nginx/htmlEXPOSE 80CMD ["nginx", "-g", "daemon off;"]
Enter fullscreen modeExit fullscreen mode

There are 4 stages in this docker file.

Thebase stage

In this stage, we build the base image, copying the files from the project and simply doingnpm install

Thedev stage

This is the stage that we want to target if we are building this image fordev. More on how to do this in a bit.

Thebuild stage

This stage exists so that theprod stage would be able to copy the generated static files for serving.

Theprod stage

This is the stage that we would target when building this image for production.

How to target astage in Dockerfile

Finally, now that we have a Dockerfile that can servedev andproduction, to build an image that is specific for dev, we use the--target argument as so:

docker build-t mutistage:latest--target=dev
Enter fullscreen modeExit fullscreen mode

This would make Docker only build up till thedev stage and nothing else.

Similarly to build for production we simply do

docker build-t mutistage:latest--target=prod
Enter fullscreen modeExit fullscreen mode

With this, we can maintain the same file for these two environments.

Top comments(3)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
managedkaos profile image
Michael
  • Location
    West
  • Work
    Server Farmer
  • Joined

Thanks for sharing this! I knew about docker stages but not how to use them with the target switch. Nice. 😎

CollapseExpand
 
boldbigflank profile image
♫Alex Swan
  • Joined

This was really helpful! Does this method mean a Docker container without a specified target will be running both? Do prod stage builds have an unused dev server running too, since it builds all the way through?

CollapseExpand
 
kurealnum profile image
Oscar
18 y/o, full-stack web dev specializing in backend development, content creator, low level programmer (aka Rust and C enjoyer). nvim & arch user
  • Email
  • Location
    United States, Virginia
  • Education
    University of Mary Washington (current student)
  • Joined

I'm about a year late for this, but thank you so much! Saved me a few hours.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Solution driving engineer with focus on optimizing for efficiencies in people, processes and systems.Enjoy solving technical problems with tools like Javascript, PHP, Terraform amongst others.
  • Location
    Lagos Nigeria
  • Work
    Senior Software Engineer
  • Joined

More fromSegun Olaiya

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp