Closed nmaaiken closed 2 years ago
I feel like this was discussed once but I can't remember what we said 🤔
Do you remember? @code-asher @jawnsy
It would be nice to see if we can optimize the size though. I haven't done that before, but would be curious to learn/help!
I also feel like we might have talked about it but I do not recall any specifics.
The reason we have the image we have now is because it is a familiar environment for developers (Ubuntu with all the stuff you would expect like curl).
Maybe what we can do is have a minimal image with code-server then extend that to make our main image and you can choose which to use. Unless we want to use something like Alpine for the smaller image in which case it would need to be separate.
I looked into this a little bit, and according to the Dive CI tool, we currently waste about 200MB due to adding some release package files that are subsequently deleted:
Analyzing image...
efficiency: 74.4829 %
wastedBytes: 236665266 bytes (237 MB)
userWastedPercent: 29.7167 %
Inefficient Files:
Count Wasted Space File Path
2 117 MB /tmp/code-server_3.11.1_amd64.deb
2 115 MB /tmp/code-server_3.11.1_arm64.deb
Unfortunately, docker buildx bake
does not seem to support the --squash
flag that docker buildx
does. There also doesn't seem to be a way to mount /tmp as a tmpfs. So unfortunately, there doesn't seem to be an easy way to reduce the image size much, though it's certainly possible with some effort.
There's some third-party commands like docker-squash that might be able to do this, but I don't think we'd want to introduce a tool like that to our build process. Also, since the image is 915MB, reducing it by 230MB still results in a ~680MB image.
Other options are to look into UBI Micro or UBI Minimal images to have a smaller footprint, but these images are also much less usable from a development perspective due to fewer dependencies available.
@nmaaiken Can you provide more detail on your use case, and why a smaller image helps for you? We could certainly consider adding an additional image type, but this entails some long-term maintenance cost on our end, since we have to keep building that image
@jawnsy sorry for the delay on my side. We are using code-server to implement a cloud-hosted, browse-able code-catalogue for our developers. This involves the need for user-specific workspaces, that may result in the need for simultaneously running containers
Even though switching to alpine as a base would be great there's no real need to go this far. Switching to debian-slim as a base would give you almost the same base as ubuntu but it's much smaller.
EDIT: I've checked ubuntu images now and they look also small so that is not the case. For some reason I remember them being much larger.
There is at least one quick win I already successfully built locally. Replacing this:
RUN ARCH="$(dpkg --print-architecture)" && \
curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.5/fixuid-0.5-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - && \
chown root:root /usr/local/bin/fixuid && \
chmod 4755 /usr/local/bin/fixuid && \
mkdir -p /etc/fixuid && \
printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml
COPY release-packages/code-server*.deb /tmp/
COPY ci/release-image/entrypoint.sh /usr/bin/entrypoint.sh
RUN dpkg -i /tmp/code-server*$(dpkg --print-architecture).deb && rm /tmp/code-server*.deb
with:
RUN ARCH="$(dpkg --print-architecture)" && \
curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.5/fixuid-0.5-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - && \
chown root:root /usr/local/bin/fixuid && \
chmod 4755 /usr/local/bin/fixuid && \
mkdir -p /etc/fixuid && \
printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml && \
curl -fsSL "https://github.com/cdr/code-server/releases/download/v3.12.0/code-server_3.12.0_$ARCH.deb" -o code-server.deb && \
dpkg -i code-server.deb && \
rm code-server.deb
COPY ci/release-image/entrypoint.sh /usr/bin/entrypoint.sh
What this does is downloading only the relevant .deb file, install it, and remove it in the same Docker RUN
command. The original downloads three different .deb files in a separate COPY
command, then installs one and removes all of them in a separate layer, which results in a far larger image. My proposed changes reduce the image size from 1.1GB to 736MB (uncompressed).
By the way: I hardcoded the version of code-server, but this could just as easily be an ARG
that's defined in the build command.
In general my tip would be to use as little separate RUN
commands as possible, since all of them add new layers (which usually results in a bigger image). While having many separate RUN
commands may be useful during development (since you make use of the caching of untouched layers, resulting in less build-time) it's best to merge as many of them as possible for the release-image.
I noticed this issue as well, and came up with a slightly different version of @PeterBennink's proposed fix: #5068
Instead of downloading the .deb package from Github during the build, I retained the current approach of copying the packages from the release-packages
directory in the local context. But I modified the Dockerfile to use a multi-stage build, so that the package files are never actually stored in the main build stage. This achieves the same size reduction while hopefully being a little bit more self-contained of a change.
Also, it's worth noting that excluding these files causes a disproportionate reduction in the compressed size of the image, since .deb files are relatively incompressible.
Hello, is it possible to create a smaller docker image for production purposes? I would be happy to make a contribution.