You are tasked with optimizing the container image for a Next.js application.
The source code for the application is located in the ~/app
directory,
along with an initial Dockerfile.
However, the current setup does not adhere to containerization best practices.
Your goal is to improve the Dockerfile and create a production-ready container image.
Build a Docker image named registry.iximiuz.com/app:v1.0.0
that meets the following requirements:
- Base Image:
- Use an optimal Node.js base image.
- Ensure the Node.js version is the active LTS version.
- Security:
- The image must run as a non-root user.
- Include only necessary packages and files.
- Performance:
- The final image size must not exceed
300 MB
.
- Runtime:
- The container should not depend on
npm
at runtime. - The application must:
- Listen on
0.0.0.0:3000
. - Include all assets from the
public
folder. - Serve APIs and static files correctly.
- Listen on
- Testing:
- Verify the application by running a container and checking the main page and the API handlers responses.
The final solution will be validated using automated checks. You can access dynamic hints from the checks by clicking the task box below.
Good luck! π
Hint 1 π‘
If you're new to Docker, you may want to solve this simpler challenge first: Build and Publish a Container Image With Docker
Hint 2 π‘
One of the tricky parts when containerizing a Node.js application is choosing the right base image. You can find many variants of Node.js base images, but not all of them are suitable for production use. If you don't know what option is best for your case, check out this material on how to choose a Node.js container image for your application.
Hint 3 π‘
Modern Node.js applications tend to depend on lots of packages. Some of these packages (e.g., linters, formatters, etc.) are needed only during the development time, while others (e.g., the framework's runtime, libraries, etc.) are needed at production time, too.
The node_modules
folder containing both development and production dependencies is usually quite large,
and it should never be included in the production container image.
Luckily, frameworks like
Next.js (src)
or Nuxt (src)
have a way to produce a standalone build of the application,
that doesn't require the node_modules
folder at runtime at all (usually via npm run build
).
However, to build a standalone bundle, you need to install all dependencies first, so if you're using a single-stage build, you'll end up with a large image anyway:
To separate the build- and runtime dependencies, a multi-stage Docker build can be used:
If you're not familiar with this technique, check out this tutorial on how to produce smaller container images with multi-stage builds.
Hint 4 π‘
Wondering why the image should not depend on npm
at runtime?
First of all,
it's an extra dependency that you probably don't even want to have in the production image because it increases the image size and the attack surface.
Second, it often messes with the graceful termination of the container:
Check out this challenge for more details: Ensure a Graceful Termination for a Containerized Node.js Application
Level up your Server Side game β Join 9,000 engineers who receive insightful learning materials straight to their inbox