If you're just here to copy and paste, here's the final Dockerfile that will produce an image for your Astro app:
FROM node:20-alpine AS base
WORKDIR /app
# By copying only the package.json and package-lock.json here, we ensure that the following `-deps` steps are independent of the source code.
# Therefore, the `-deps` steps will be skipped if only the source code changes.
COPY package.json package-lock.json ./
FROM base AS prod-deps
RUN npm install --omit=dev
FROM base AS build-deps
RUN npm install
FROM build-deps AS build
COPY . .
RUN npm run build
FROM base AS runtime
COPY --from=prod-deps /app/node_modules ./node_modules # Copy dependencies
COPY --from=build /app/dist ./dist # Copy the built output
# Bind to all interfaces
ENV HOST=0.0.0.0
# Port to listen on
ENV PORT=4321
# Just convention, not required
EXPOSE 4321
CMD node ./dist/server/entry.mjs # Start the app
And here's the .dockerignore file:
.DS_Store
node_modules
dist
To build and run the image, use these commands:
docker build -t astro .
docker run -p 4321:4321 astro
Not just here to copy and paste? Let's go over what's happening in the Dockerfile!
The Setup
For this tutorial, I assume you have a basic Astro project set up. If you have a different setup, you might need to adjust the Dockerfile accordingly.
Typically, you'd run npm install and then npm run dev to work locally. However, for deployment, we want to build the app and serve the files from a server. So instead, we'll use npm run build to create the files and then serve them.
Let's dive into the details of the Dockerfile.
The Dockerfile
FROM node:20-alpine AS base
WORKDIR /app
# By copying only the package.json and package-lock.json here, we ensure that the following `-deps` steps are independent of the source code.
# Therefore, the `-deps` steps will be skipped if only the source code changes.
COPY package.json package-lock.json ./
FROM base AS prod-deps
RUN npm install --omit=dev
FROM base AS build-deps
RUN npm install
FROM build-deps AS build
COPY . .
RUN npm run build
FROM base AS runtime
COPY --from=prod-deps /app/node_modules ./node_modules # Copy dependencies
COPY --from=build /app/dist ./dist # Copy the built output
# Bind to all interfaces
ENV HOST=0.0.0.0
# Port to listen on
ENV PORT=4321
# Just convention, not required
EXPOSE 4321
CMD node ./dist/server/entry.mjs # Start the app
So what's happening here?
- Base stage:
- Uses Node.js 20 on Alpine, providing a lightweight base image.
- Sets up the working directory and copies package files for dependency installation.
- Production dependencies stage:
- Installs only production dependencies, omitting dev dependencies.
- Build dependencies stage:
- Installs all dependencies, including dev dependencies needed for building.
- Build stage:
- Copies the entire project and runs the build command.
- Runtime stage:
- Starts from the base image again.
- Copies production dependencies and built files from previous stages.
- Sets environment variables for host and port.
- Exposes port 4321 (Astro's default port).
- Starts the Astro app using the built server entry point.
This multi-stage approach optimizes the build process and keeps the final image size smaller by separating build and runtime environments.
Make sure to add the .dockerignore
file to ignore the node_modules
and dist
folders. This will speed up the build process and reduce the image size.
Deployment
You can deploy this Docker container to any cloud provider that supports Docker. For example, you could use platforms like Heroku, DigitalOcean, or AWS ECS. Because I am the co-founder of Sliplane, I will show you how to deploy it there.
After signing up, you can create a new service by selecting your Github Repository. Then just keep the default settings and click on deploy.
After deployment your astro app will be available under a subdomain of sliplane.app, usually its just your service name.
You can also see the logs of your app, see metrics such as cpu and memory usage, add persistant storage and much more. Whenever you push to your repository, Sliplane will automatically deploy your app.
If you want to try out Sliplane, the first 2 days are free! Try it out and let me know what you think :)
Next Steps
Is there anything else you want to know? Do you need help dockerizing your Astro app? Do you need help deploying it to a specific platform? Feel free to reach out!
You can find me on X or just comment here on this blog.
Cheers,
Jonas
Top comments (4)
We really love Astro over at Gorombo Software Development. We are working with using AI to build Astro apps!
Nice article. Short, sweet and to the point.
Astro is so cool ngl