a year 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
a year ago
what takes the most time to run?
a year ago
I believe you'd shared a tool somewhere with which I could extract build logs. Would that be helpful?
a year ago
Building takes ~80 secs
a year 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
a year ago
so it's the building, exporting and pushing of layers, and pushing the manifest which take the most time.
a year ago
a year ago
I can't seem to get the bookmarklet to work with my browser. Is there another way I can export this for you?
a year ago
Can't get the bookmark to work with Arc browser and injecting the JS via console doesn't work either.
a year ago
ctrl / cmd + k
-> logs
a year ago
I've created a Github Gist for you: https://gist.github.com/budivoogt/ee5e069bdb4ab5092aabfd4ecc9b6bab
a year ago
Does that work?
a year ago
a year ago
since its not the full logs, nope doesnt work
a year ago
okay that one works
a year ago
Sweet 👏🏼
a year ago
do you happen to know how big this image is?
a year ago
How can I find out?
a year ago
by building locally
a year ago
Once I do that, where can I find the image? Does it get created in my project folder?
a year ago
Sorry I'm new to Docker.
a year 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?
a year 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
a year ago
OK I will try.
a year 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?
a year ago
<#727685388893945877> 5) don't ping team or conductors
a year ago
1.16gb is still big but totally doable imo
a year ago
Oh sorry! I'll remove the tag.
a year ago
Done 🙂
a year ago
Do you think there are any further optimisations I could make?
a year ago
🤔 I don't think so, I never had to optimize the size of my images
a year ago
so I can't really say
a year 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
a year ago
How can I reduce the size of the image?
a year ago
And how would I know where to find the correct mount targets?
a year 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"
a year ago
Not sure if I derived my mounts correctly from that.
a year 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/
a year ago
mine went from ~900MB to ~350MB after optimization
a year 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.
a year ago
yes no issues with the -slim
node image variants
a year ago
How would I incorporate that into the creation of my image? Can I run docker-slim in the Dockerfile somehow?
a year ago
Any hints or example repos I could take a look at, perhaps?
a year ago
oh sorry i thought you wanted to use slim images, no railway does not support running docker slim
a year ago
I thought so -- thanks for clarifying.
a year 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.
a year ago
🎉
a year ago
Any feedback on this? How do I know if I'm using the right mount targets?
a year ago
im sure you arent the first to do this on the vast internet, and it wouldn't be specific to railway
a year ago
Hint taken. I will do more research.
a year 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?
a year ago
you mean service id
a year ago
and in that case, it will fail
a year 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.
a year 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?
a year ago
again, service id, not session id
a year ago
Sorry yes, typo.
a year ago
But my question still stands.
a year ago
yes you do need to hardcore that service id for every service you deploy to
a year ago
I see. Understood.