I assume that the problem is that your website is missing the expected style, correct?
At a first look it seems that your CSS bundle, https://stage2.speicher.ltd/css/app-ada34c09c604a70f521cfb3887f52835.css, does not contain all the rules that one would expect looking at your HTML. For example, there are no rules for the HTML classes max-w-screen-xl, mx-auto, and many of those framework classes that you use.
In other words your assets are correctly compiled and served, but they miss some expected content. It’s hard to guess why without looking at your code, but first of all I would look into your assets to make sure that all the necessary CSS is included.
the question is more like: if I do a (local) mix release everything is in place and all CSS rules are honored - but without touching anything - when I do (the same) mix release, only now in a container (which is what technically is happening in a dokku deploy) the css is less than half the size!!
-rw-r--r-- 1 walther staff 28898 19 Jun 10:25 app-e8d95eb985318b44f69a005c82e5464e.css
-rw-r--r-- 1 walther staff 6168 19 Jun 10:25 app-e8d95eb985318b44f69a005c82e5464e.css.gz
vs the docker
-rw-r--r-- 1 nobody nobody 10309 Jun 19 08:17 app-ada34c09c604a70f521cfb3887f52835.css
-rw-r--r-- 1 nobody nobody 2775 Jun 19 08:17 app-ada34c09c604a70f521cfb3887f52835.css.gz
I’m going hunting in a dokku forum - this has obviously nothing to do with neither Elixir, nor Phoenix, but has to be a dokku thing of sorts!
If I do a local docker-compose up I bring my container alive on my own machine - with the “true” filesize of the bundled css, hence it has to be dokku that somehow fiddles with whatever part of the package
But I will report back onec I get this sorted out!
“you hit me right in the pantalone, partener” as Hrundi V Bakshi a.k.a Peter Sellers would have said
I’m in no way what so ever fluent in Webpack & Friends - operating on a strict “monkey orders” command by command.
I remember seeing PurgeCSS when I was meddling with Tailwind in order to get it glued into the project in the first place - but either I didn’t make it to the “steamy finale” or I dodged it, sorry cannot recall.
Just to let you know, I’m responsible for the latest Dockerfile that’s in the phoenix releases documentation. So you can blame me if it doesn’t work
I just tried it again to see if anything broke but it works fine for me.
For it to work you need the following though:
Have a proper config (url, server: true for phoenix to start and such)
To test it in docker on a mac/windows machine you might have to disable the :inet6 transport option because it seems only docker on linux supports ipv6
rename my_app to your app name in the Dockerfile
I looked at your Dockerfile and here are some tips:
Don’t use COPY . .. Always be as specific as possible. Docker makes heavy use of caching layers. For example, let’s say you edit a README.md file in the root of your project. That file doesn’t have anything to do with the build itself. But because you used COPY . ., which includes README.md, you’ve invalidated the cache. That means every step after the COPY . . will be executed again even if you didn’t change anything else. If your .dockerignore isn’t configured properly you can have some really hard to trace problems. You might copy things that are compiled for your mac into the linux container for instance. Yes, I’ve seen that happen
If you have multiple RUN statements after each other, combine them into 1 run statement. Each RUN statement causes the creation of a new layer. For example, RUN chown -R nobody:nobody /app basically creates a copy of all the files in the app directory, just with new permissions. The originals aren’t changed and are still in the previous layer. Your image file just grew a lot in size, even though it’s “just” a permission change.
Try to separate the run/copy statements for elixir files and the assets. Because the COPY . . is at the top, all the npm commands are executed again, even when you only change elixir files.
Use multistage Dockerfiles. Right now you have only 1 FROM. This means that ALL build dependencies, node_modules, source and such end up in your final image even though you don’t need them to run your application. Your final image is 576Mb. When using the Dockerfile in the release docs for a new phoenix project (without db) you end up with an image around 22Mb in size. A huge difference. With multistage files you can separate the image/files you need for your build from the minimal image you need to just run the application.
This is basically why the Dockerfile in the release docs is the way it is. It’s all about optimising for caching (everything for the build itself) and size (the final image that runs in production).
You can optimise even further using buildkit for instance but that makes the Dockerfile a bit more complex so I didn’t include that in the docs.
On the topic of multistage - oh I’d like that but Dokku complains about missing intermediates because it does a (too) wonderful job of cleaning up the build stage intermediates - and I haven’t solved how to keep them long enough to utilize multistage
@wdiechmann Ah, I don’t know anything about Dokku but if it’s really the case that it doesn’t support multistage builds I’d consider that a serious red flag. It’s still a single Dockerfile and single docker build so there shouldn’t be any issues. Multistage is one of the most important docker features to me.
@praveenperera nice clean Dockerfile. I’d probably create a single base for both the deps-getter and release-builder steps since they both do the same apk installs. You shouldn’t need the mkdir commands. WORKDIR already creates the directory if it doesn’t exist and most others should be created automatically as well I believe. And I’d probably combine multiple COPY and multiple RUN statements wherever possible. It’s easier to read now though and doesn’t make too much of a difference anyway since they aren’t in the final image.