8 months ago
I want to ask for feedback on my Dockerfile. This is the first time I've set up caching.
This Dockerfile works. My first deploy of this file was 143 secs, the second 124 secs. But that's still really slow IMO for that second try. Have I set this up properly for Node and PNPM as package manager?
Is there anything else I can do to speed these builds up?
I also noticed it's required to hardcode your session-id
. I've now bound this to the service-id
of my main
production environment in Railway. What are the implication of this when a different environment is created in Railway for your project, for example when you create a new PR on Github?
Thanks!
# Use Node.js as the base image
FROM node:20-alpine
# Install pnpm
RUN npm install -g pnpm
# Set working directory
WORKDIR /app
# Install dotenvx
RUN curl -sfS https://dotenvx.sh/install.sh | sh
# Copy package.json and pnpm-lock.yaml
COPY package.json pnpm-lock.yaml ./
# Install dependencies with caching
RUN --mount=type=cache,id=s/e87cdb12-ca40-472a-b18b-fc6f19c34f3f-/root/.local/share/pnpm/store,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile
# Copy the rest of the application code
COPY . .
# Specify the environment variables needed at build time
ARG DOTENV_PRIVATE_KEY_PRODUCTION
# Build the application with caching
RUN --mount=type=cache,id=s/e87cdb12-ca40-472a-b18b-fc6f19c34f3f-/root/.cache/pnpm,target=/root/.cache/pnpm \
pnpm run build
# Expose the port the app runs on
EXPOSE 3000
# Start the application
CMD ["pnpm", "start"]
0 Replies
8 months ago
what takes the most time to run?
8 months ago
I believe you'd shared a tool somewhere with which I could extract build logs. Would that be helpful?
8 months ago
Building takes ~80 secs
8 months ago
Here I filtered the logs for done
:
#12 80.01 ✔ done
#12 DONE 80.7s
#13 exporting layers 15.2s done
#13 exporting manifest sha256:7a3c7f748177c383ddcb646668c4feda059f1169a216e894fd1002ea0f51934c 0.3s done
#13 exporting config sha256:7b82807699583bf53ac0eb6662ad7c2becd54cbb7e53ac67cbd19706e62f3a35 done
#13 exporting attestation manifest sha256:6dcc37b278a65409922832067c6f3c92afec59e903491135fa55874c085501ea done
#13 exporting manifest list sha256:4faeed252081451d247c1a960c7e55a06ccba801bac34cdf1dd2f093d8f353e5 done
#14 DONE 0.0s
#13 pushing layers 15.7s done
#13 pushing manifest for us-west1.registry.rlwy.net/e87cdb12-ca40-472a-b18b-fc6f19c34f3f:b7081d8b-891b-480a-a771-b6c31bd57b36@sha256:4faeed252081451d247c1a960c7e55a06ccba801bac34cdf1dd2f093d8f353e5 1.3s done
#13 DONE 32.5s
8 months ago
so it's the building, exporting and pushing of layers, and pushing the manifest which take the most time.
8 months ago
8 months ago
I can't seem to get the bookmarklet to work with my browser. Is there another way I can export this for you?
8 months ago
Can't get the bookmark to work with Arc browser and injecting the JS via console doesn't work either.
8 months ago
ctrl / cmd + k
-> logs
8 months ago
I've created a Github Gist for you: https://gist.github.com/budivoogt/ee5e069bdb4ab5092aabfd4ecc9b6bab
8 months ago
Does that work?
8 months ago
8 months ago
since its not the full logs, nope doesnt work
8 months ago
okay that one works
8 months ago
Sweet 👏🏼
8 months ago
do you happen to know how big this image is?
8 months ago
How can I find out?
8 months ago
by building locally
8 months ago
Once I do that, where can I find the image? Does it get created in my project folder?
8 months ago
Sorry I'm new to Docker.
8 months ago
How do I build the Docker file locally using Railway's cache? Do I have to create a new Dockerfile to build locally without the caching statements?
8 months ago
you dont build it with railway's cache, nor is that something you can do, you simply build the image, you shouldnt need to change anything
8 months ago
OK I will try.
8 months ago
I had to make a bunch of changes to the Dockerfile to get it working locally, but got the local creation of the image done. The size of the image is 1.16GB. Here's the updated Dockerfile:
# Build stage
FROM node:20-alpine AS builder
# Install pnpm
RUN npm install -g pnpm
# Set working directory
WORKDIR /app
# Install dotenvx
RUN curl -sfS https://dotenvx.sh/install.sh | sh
# Copy package.json and pnpm-lock.yaml
COPY package.json pnpm-lock.yaml ./
# Install dependencies with caching
RUN --mount=type=cache,id=s/e87cdb12-ca40-472a-b18b-fc6f19c34f3f-/root/.local/share/pnpm/store,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile
# Copy the rest of the application code
COPY . .
# Specify the environment variables needed at build time
ARG DOTENV_PRIVATE_KEY_PRODUCTION
# Set Node options for increased memory
ENV NODE_OPTIONS="--max-old-space-size=4096"
# Build the application with caching
RUN --mount=type=cache,id=s/e87cdb12-ca40-472a-b18b-fc6f19c34f3f-/root/.cache/pnpm,target=/root/.cache/pnpm \
NODE_ENV=production pnpm run build
# Production stage
FROM node:20-alpine
# Install pnpm in the production stage
RUN npm install -g pnpm
# Set working directory
WORKDIR /app
# Copy the build output and package.json from the builder stage
COPY --from=builder /app/build ./build
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/pnpm-lock.yaml ./pnpm-lock.yaml
# Install only production dependencies
RUN pnpm install --prod
# Expose the port the app runs on
EXPOSE 3000
# Start the application
CMD ["pnpm", "start"]
What do you think of the new Dockerfile?
And are there any ways you think I can speed up builds?
8 months ago
<#727685388893945877> 5) don't ping team or conductors
8 months ago
1.16gb is still big but totally doable imo
8 months ago
Oh sorry! I'll remove the tag.
8 months ago
Done 🙂
8 months ago
Do you think there are any further optimisations I could make?
8 months ago
🤔 I don't think so, I never had to optimize the size of my images
8 months ago
so I can't really say
8 months ago
you can definitely get it smaller than 1.16GB.
it's also possible your mount targets are incorrect, aka not the actual path pnpm stores the cache at, so nothing actually gets cached
8 months ago
How can I reduce the size of the image?
8 months ago
And how would I know where to find the correct mount targets?
8 months ago
I referenced this https://github.com/railwayapp/nixpacks/blob/main/src/providers/node/mod.rs thinking this was the right example for node
and found pnpm cache mentioned as such: const PNPM_CACHE_DIR: &str = "/root/.local/share/pnpm/store/v3"
8 months ago
Not sure if I derived my mounts correctly from that.
8 months ago
these articles (part 1 & 2) were pretty good walkthrough on how to reduce image sizes https://lengrand.fr/reducing-dockers-image-size-while-creating-an-offline-version-of-carbon-now-sh/
8 months ago
mine went from ~900MB to ~350MB after optimization
8 months ago
Nice I incorporated some of the tips.
Does the Slim package work with Railway too? Asking since it seems CLI driven so not sure if you could incorporate that into the build file.
8 months ago
yes no issues with the -slim
node image variants
8 months ago
How would I incorporate that into the creation of my image? Can I run docker-slim in the Dockerfile somehow?
8 months ago
Any hints or example repos I could take a look at, perhaps?
8 months ago
oh sorry i thought you wanted to use slim images, no railway does not support running docker slim
8 months ago
I thought so -- thanks for clarifying.
8 months ago
I was about to halve the size of the image though by pruning the node and pnpm modules in the build phase, and then explicitly copying the node_modules
in the production step instead of re-installing the dependencies there.
8 months ago
🎉
8 months ago
Any feedback on this? How do I know if I'm using the right mount targets?
8 months ago
im sure you arent the first to do this on the vast internet, and it wouldn't be specific to railway
8 months ago
Hint taken. I will do more research.
8 months ago
Also I had this remaining question:
I also noticed it's required to hardcode your session-id. I've now bound this to the session-id of my main production environment in Railway. What are the implication of this when a different environment is created in Railway for your project, for example when you create a new PR on Github?
8 months ago
you mean service id
8 months ago
and in that case, it will fail
8 months ago
But so far, when I've been testing these builds and put my new code in a new PR, a new Railway environment was started which deployed just fine with the Dockerfile that had my service-id included.
8 months ago
I don't understand the limitations of this properly. Is the idea that I hardcode the service-id
of each Railway production environment that I'll be deploying the image in?
8 months ago
again, service id, not session id
8 months ago
Sorry yes, typo.
8 months ago
But my question still stands.
8 months ago
yes you do need to hardcore that service id for every service you deploy to
8 months ago
I see. Understood.