32-bit Linux docker template to run phoenix applicaiton

Over there at https://fly.io they are offering 256MB VM for free. 256MB of memory is not much; and I want to make every MB count. One way I know to reduce memory usage is to run the whole stack in 32 bit. Does anyone have a good dockerfile that is on 32 bit Linux and work well with Elixir/Phoenix? Thanks a lot.

4 Likes

Is the official Elixir image not doing the job?

Theoretically it should work; however I am a complete docker newbie so I’d like to know other’s experience. There is usually some hidden trap for running 32 bit linux these days. For example, 32 bit linux is not a supported node.js arch anymore.

Just an FYI, the moment I went from erlang 23.x to 24.x I couldn’t compile my elixir app unless I went to a 2GB digital ocean instance(from 1GB).

I still can; the trick is to use a swapfile. In fact, I compile both erlang and elixir in my 1GB VPS (64-bit linux)
There is no point to run 64 bit in 1GB and below; but sadly most hosting companies don’t offer the option anymore. I hope by using docker I can regain the full control.

1 Like

Cool, thanks for the swap file tip.

Just to make sure: you’re looking for 32-bit x86, not ARM, correct?

1 Like

Would ARM 64 consume less RAM compared to x86 32 and 64-bit architectures?

Yes, 32 bit x86 linux.

I doubt it. Moving from 32-bit to 64-bit doubles your memory requirements for storing pointers which 99.99% of all projects ever use – on one level or another.

1 Like

Shout out to the people working for fly.io. Docker actually works with a 32-bit image and can build one as such:

---> [Warning] The requested image's platform (linux/386) does not match the detected host platform (linux/amd64) and no specific platform was requested
 ---> Running in 72b316f7113c
Removing intermediate container 72b316f7113c
 ---> a32222658cc2
Successfully built a32222658cc2

However, flyctl does not:

Step 9/12 : COPY --chown=nobody:root _build/prod/rel ./
Error error building: error rendering build status stream: failed to get destination image "sha256:25b4cabe2bbca2c88fe3d98e751789319c1c54281848836723db42c311d8929d": image with reference sha256:25b4cabe2bbca2c88fe3d98e751789319c1c54281848836723db42c311d8929d was found but does not match the specified platform: wanted linux/amd64, actual: linux/386

If I choose to push the image directly, as in: flyctl deploy -i a32222658cc2 again it fails:

--> Pushing image done
Image: registry.fly.io/gara:deployment-1637358085
Image size: 138 MB
==> Creating release
Error Validation failed: Image must be amd64 architecture for linux us

I think running a 32 bit image in the interest of saving memory is a valid user case, especially in the low end VMs. I even consider it is one of the strength of elixir/erlang stack, which run 32 bit fully supported, unlike node.js or Go.

1 Like

Bummer …

I did it. I have to jump through several hoops, but here you are:

https://gara.fly.dev/dashboard/

fly 32-bit! Compare to the the 64 bit version of the same app, the memory footprint as reported by live_dashboard shrunk from 58MB down to 34MB, not too shabby, right?

from fly.io’s console the saving is even more so:

See the sudden drop in memory footprint around 8:04pm

5 Likes

Grats on making it work. :slight_smile:

I personally wouldn’t risk my app ever spiking load and needing more than 2GB of RAM – in which case heavy swapping or outright murder by the Linux OOM monitor will happen – but if the hosting’s RAM is no more than 2GB anyway then I can see the appeal in reducing the absolute memory usage by moving from 64-bit to 32-bit pointers.

Running partially in 32 bit even has it usage when you have more than 2GB, precisely because of the OOM killer. Let’s say you have a database and some other smaller jobs running on the same box. Obviously you want to run the database in 64 bit. However, you may want to run the other small stuff in 32 bit, if in all reasonable situation they should not consume more than 2GB. If they misbehave and suddenly consume a lot of RAM they will crash because of the 32 bit ceiling, not because of the OOM killer. It is a less brutal death (malloc fails, and sometimes you can recover) and on top of that, your big database is safe.

I wrote a blog post summarizing what I did to run a 32-bit Phoenix application on fly.io:

5 Likes

I was about to ask for this. Thank you for sharing!

Great article.
Any chance that you will share your docker file/image?

The dockerfile is in the github repo at the end of the article:

I only use Docker to deploy, and used an LXC container to build the OTP release. Theoretically anything you can do with LXC you can do in Docker too; but I am not fluent with Docker to make that happen.

2 Likes