[HN Gopher] Best practices around creating production ready web ... ___________________________________________________________________ Best practices around creating production ready web apps with Docker Compose Author : nickjj Score : 183 points Date : 2021-06-01 18:25 UTC (4 hours ago) (HTM) web link (nickjanetakis.com) (TXT) w3m dump (nickjanetakis.com) | oliwary wrote: | I have really enjoyed working with docker compose for | development. For production, there is a great guide by the | creator of FastAPI on how to spin up a docker swarm cluster to | use almost the same files here: | | https://dockerswarm.rocks/ | barbazoo wrote: | > web: | | > <<: _default-app | | > ... | | > worker: | | > <<: _default-app | | This is always somewhat of a code smell to me. This makes me want | to dig deeper and see if the two use cases shouldn't have been | separated into separate Docker files or even separate apps. | TameAntelope wrote: | I tend to start with monolith and split things out when I get | frustrated with how coupled they are. | pentium166 wrote: | It seems reasonable to me (for a compose-in-prod setup). The | standard setup (at least for Rails, in my experience) is that | the web server and background job processor will have the same | dependencies and nearly identical configuration. Until the app | has gone off the rails and I really do need to have the server | and worker diverge, this approach seems like less to worry | about than maintaining multiple images and duplicated but 98% | identical container definitions. | znpy wrote: | Pro-tip: nowadays podman can pretend to be a kubernetes cluster | and launch pod And deployment definitions (in yaml, of course). | | That of course is way close to the "production" in "production | ready". | buildbot wrote: | Without podman-compose too! I didn't know this was the case | now: https://www.redhat.com/sysadmin/compose-kubernetes-podman | ecliptik wrote: | That sounds really cool. Do you happen to have a good link for | this? | buildbot wrote: | Not GP, but Perhaps https://www.redhat.com/sysadmin/compose- | kubernetes-podman? | 2OEH8eoCRo0 wrote: | Also daemonless and rootless | nonameiguess wrote: | I had remembered docker's own documentation in the past | recommending against using compose at all in production, but that | is apparently no longer the case: | https://docs.docker.com/compose/production/ | | I'm fairly surprised by this. You can deploy a fairly similar | compose file into a Docker swarm cluster, but if you're doing a | single-server deployment of everything, that is awfully brittle | for production, to say nothing of considerations brought up in | other comments where you may be using managed services from a | cloud provider for things like database and caching in production | but you're probably just spinning up a local postgres server on | your laptop for development. | throwaway2139 wrote: | https://github.com/docker/compose-on-kubernetes looks dead now, | maybe for misguided political reasons while they remain in | denial that swarm might compete? But it's too bad, there's no | reason some k8s api/operator thing can't make this | frictionless. | | Still, someone already mentioned docker-desktop having some | tricks for deploying straight to aws and [there is definitely a | way to do this with | ecs](https://aws.amazon.com/blogs/containers/deploy- | applications-...). There's also tools like kompose which | translate configs automatically and are suitable for use in a | pipeline, so the only thing you need is a compose file in | version control. | | So yes, you can still basically use compose in production, even | on a non-swarm cluster, and it's fine. A lot of people that | push back against this are perhaps just invested in their own | mad kubectl'ing and endless wrangling with esoteric templates | and want to push all this on their teammates. From what I've | seen, that's often to the detriment of local development | experience and budgeting, because if even your dev environment | always requires EKS, that gets expensive. (Using | external/managed databases is always a good idea, but beside | the main point here I think. You can do that or not with or | without docker-compose or helm packages or whatever, and you | can even do that for otherwise totally local development on a | shared db cluster if you design things for multi-tenant) | | At this point I'll face facts that the simple myth here | (docker-compose is merely a toy) is winning out over the | reality (docker-compose is partly a tool but isn't a platform, | and it's just a format/description language). But consider.. | pure k8s, k8s-helm, ECS cloudformation, k8s-terraforming over | EKS, and docker-compose _all_ have pretty stable schemas that | require almost all the same data and any one of them could | pretty reasonably be considered as a lingua-franca that you | could build the other specs from (even programmatically). | | From this point of view there's an argument that for lots of | simple yet serious projects, docker-compose should win by | default because it is at the bottom of the complexity ladder. | It's almost exactly the minimal usable subset of the abstract | description language we're working with, and one that's easy to | onboard with and requires the least dependencies to actually | run. For example: even without kompose it's trivial to automate | pulling data _out_ of the canonical docker-compose yaml and | injecting that _into_ terraform as part of CD pipeline for your | containers on EKS; then you keep options for local-developer | experience open and you 're maintaining a central source of | truth for common config so that your config/platform is not | diverging more than it has to. | | I'm an architect who works closely with ops, and in many ways | not a huge fan of docker-compose. But I like self-service and | you-ship-it-you-run it kinds of things that are essential for | scaling orgs. So for simple stuff I'd rather just use compose | as the main single-source-of-truth than answer endless | bootstrappy questions about k8s or ECS if I'm working with | others who don't have my depth of knowledge. (Obviously compose | has been popular for a reason, which is that kubernetes really | is still too complicated for a lot of people and use-cases.) | Don't like these ready-made options for compose-on-ECS, or | compose-to-k8s via kompose? Ok, just give me your working | docker-compose and I'll find a way to deploy it to any other | new weird platform, and if I need some pull-values/place- | values/render-template song and dance with one more weird DSL | for one more weird target deployment platform, then so be it. | I've often found the alternative here is a lot of junior devs | deciding that deployment/dev-bootstrap is just too confusing, | their team doesn't help them and pushes them to an external | cloud-engineering team who doesn't want to explain this again | because there's docs and 10 examples that went unfollowed, so | then junior devs just code without testing it all until they | have to when QA is broken. Sometimes the whole org is junior | devs in the sense that they have zero existing familiarity with | docker, much less kubernetes! Keep things as simple as | possible, no simpler. | | Seen this argument a million times, and no doubt platform | choices are important but even pivoting on platforms is | surprisingly easy these days. When you consider that compose is | not itself a platform but just basically a subset of a wider | description language, this all starts to seem a bit like a json | vs yaml debate. If you need comments and anchors, then you want | yaml. If you need serious packaging/dependencies of a bunch of | related microservices, and a bunch of nontrivial JIT value | lookup/rendering, then you want helm. But beyond org/situation | specific considerations like this, the difference doesn't | matter much. My main take-away lately is that leadership needs | to actually decide/enforce where the org will stand on topics | like "local development workflows"; it's crazy to have a team | divided where half is saying "we develop on laptops with | docker-compose" and half is saying "we expect to deploy to EKS | in the dev environment". In that circumstance you just double | your footprint of junk to support and because everyone wants to | be perfectly pleased, everyone is annoyed. | reportt wrote: | Using the docker-compose.override.yml helps with that. In local | you can just have those services/configurations added, and then | the production environment doesn't even need to know they | exist. | wiktorcie wrote: | just use dokku instead, it's much easier. Why bother with docker | compose? | clintonb wrote: | Dokku has a lot of overhead to run. | layoric wrote: | Not for production, but used it for deployments to remote servers | via SSH using GitHub Actions. Wrote a guide and video tutorial of | how to as well, it uses nginx proxy and surprisingly updates were | zero down time since the nginx proxy didn't change and handles | switching app ports seamlessly. For low traffic app could be used | for production but I wouldn't since it is a single server | deployment setup. Good for dev/test environment, I use this | pattern for 20+ live demo apps on a single server. | | Tutorial: https://docs.servicestack.net/do-github-action-mix- | deploymen... | | Video: https://youtu.be/0PvzcnxlBvc | peterthehacker wrote: | Running docker compose in production is not a good practice from | what I understand. The persistence layers, like MySQL or Redis, | shouldn't be managed with local volumes. If you want to do | something like this then kubernetes with persistent volume claims | would be better, but running databases in k8s can be pretty | tricky. Most of the time RDS is the best practice for your DB. | zmmmmm wrote: | Swapping out the persistence layer in prod vs dev is one of the | topics covered by the article, for the reasons you mention. | 0xbadcafebee wrote: | Docker Compose now works natively with AWS ECS, so you could | conceivably "scale" Docker Compose. Plus there's AWS's _ecs-cli_ | which can work, though IIRC you basically have to maintain two | different configs, one for local development, one for remote. | | And that's the general flaw in using Compose outside of local | development. It's simply not designed as a general purpose (and | thus large-scale) deployment orchestrator. If you get it working | locally, you _probably_ need a different setup for remote. That | affects things like testing, which means it 's not really the | same in dev as in prod. And even if it were, Compose isn't | persistent, meaning it's just a script to start jobs on some | other thing. | | Every time I've worked on a team that tried to do Compose in | production (or even just for CI) it ended up a weird snowflake or | with duplicate processes, and we replaced it with something more | standard. My standard advice now is to model both production and | local development to be as close as possible and then pick the | simplest method to support that use case. In general this means | going from "Compose on one host" to Swarm/Nomad/ECS on multiple | hosts to K8s. And of course, try to make your CI use the same | exact methods you use for dev and prod, so that using CI doesn't | give you different results than in dev or prod. | mdoms wrote: | I don't understand his "Avoiding 2 Compose Files for Dev and Prod | with an Override File" point. He just says it, but never | justifies it. | nickjj wrote: | Hi, | | It's mentioned on video and briefly in the blog post. It's so | you don't have to duplicate a bunch of services between 2 files | while you slightly change a bit of configuring for those | services depending on the environment you're in, or even | running different containers all together (which is the problem | the override file solves). | randompwd wrote: | It's a terrible idea that's why. | | It comes with far more(&more dangerous) downsides than upsides. | | It's a rookie mistake for simple applications which most people | learn to not do. | reportt wrote: | The idea is that you have a core structure that is used in both | local/dev environment and the prod environment, with just the | override applying changes. For example, your local override | might have the "build" configuration, whereas the dev | environment or production environment docker-compose should not | have that configuration (assuming you are pulling from a | private registry). That single core docker-compose.yml can be | copied to any environment it needs and it should just run the | app, but if you really, really need to override something for a | specific reason, it's not hard to do it without modifying the | core docker-compose.yml. | trinovantes wrote: | Probably so you don't have duplicate settings in docker- | compose.prod.yml and docker-compose.dev.yml when the only | difference is probably just 1 line specifying NODE_ENV etc. | stevebmark wrote: | I haven't heard of using docker compose for production | development, only local development. In production I normally see | people building production images and spinning up them up in | their cloud with Terraform and whatever other infrastructure they | need, especially for databases where your local MySQL container | isn't going to be configured or provisioned like an AWS RDS | instance. What do you hand a docker-compose file off to in | production? Swarm? When would you choose this path over a | separate system to provision your production resources (like | Terraform)? | symlinkk wrote: | Why would you NOT choose this path? Local and prod are the same | with this method, that's a big advantage. | osrec wrote: | We use docker compose in production, but have our own custom | tooling based around it. | | K8s was a little too complex and docker swarm a little too | simple. Rolling our own solution was a last resort, but it | worked out well in the end - more control, deeper understanding | and no nasty surprises in behaviour while scaling etc. | dariusj18 wrote: | I found that Hashicorp Nomad fit really well in between k8s | and swarm for power to complexity. I ended up not being able | to use it because they hadn't implemented the networking | stuff that they eventually got, but it's pretty cool stuff. | ensignavenger wrote: | Docker Swarm is one option, but Docker Desktop has the ability | to deploy from a Compose file directly to AWS. There are | additional tools for other platforms. See | https://aws.amazon.com/blogs/containers/deploy-applications-... | for example. | pricechild wrote: | It's currently in preview, but https://docs.microsoft.com/en- | us/azure/app-service/quickstar... doesn't look bad. | cs02rm0 wrote: | I don't think you would in prod, unless you were happy with it | all running on one host. | | Shame really, I find compose simple and neat and k8s+terraform | an unsettling mess. | 411111111111111 wrote: | Docker swarm deploys to multiple hosts and there is also | kompose for k8s. | | I haven't used either of them in production though | namdnay wrote: | Same here, docker compose is a great little tool for local | development. You can get your apps up and running with their | respective elasticsearches and localstacks etc, then attach to | process if needed to debug | | For anything more serious, Terraform makes much more sense IMHO | nickjj wrote: | OP here. | | A lot of my clients are happily using Docker Compose in | production. Some even run a million dollar / year businesses on | a single $40 / month server. It doesn't get handed off to Swarm | or another service, it's literally docker-compose up --remove- | orphans -d with a few lines of shell scripting to do things | like pull the new image beforehand. | | You can still use Terraform to set up your infrastructure, | Docker Compose ends up being something you run on your server | once it's been provisioned. Whether or not you decide to use a | managed database service is up to you, both scenarios work. The | blog post and video even cover how you can use a local DB in | development but a managed DB in production using the same | docker-compose.yml file, in the end all you have to do is | configure 1 environment variable to configure your database at | the app level with any web framework. | merb wrote: | how do you handle no downtime deployments? how do you backup | data? | | I rather would use kompose+kustomize to convert it to k8s and | than use k3s with ingress-nginx with hostPath and backup | local volumes with velero. | zmmmmm wrote: | > I rather would use ... | | you'd rather use six complex things instead of one simple | one? | merb wrote: | well I asked, because everybody answered either with the | following: | | > we do not care about no downtime or stateless nodes and | a lb in front | | and b: | | > backup with the standard tooling or stateless nodes | | so basically they just use it mostly to "package" the | application and everything else is probably done with | different tooling. | vbsteven wrote: | I'm not the parent but I'll pitch in on this as I have a | few client projects using docker compose for production. | | No downtime deployments: I don't bother for these projects. | A minute of downtime in off-peak hours for a restart is | fine. | | Data backup: just like you would backup any other local | data: cron, rsync, pg_dump. And there isn't much local data | anyway as most services are stateless, using S3 or a | database for long term storage. | | I choose docker compose for production when I want to keep | complexity to a minimum: All I need is a cloud vm, an | ansible playbook to install docker and configure backups. | Typically in these scenarios I run the database as an OS | service and only use docker for nginx/redis and application | services. | angrais wrote: | Why do you use the database as an OS service and not in | docker? | | Using it in docker would allow easier local development, | and shorter setup time. | aprdm wrote: | How's it different than running things with pure docker or | before docker? There were backups and no downtime | deployments before docker became a thing... docker compose | is already a layer above docker (but really just docker). | merb wrote: | yeah but stuff like that is hard and not solved with | compose, you can update your compose but that would | result in downtime, so you can either do a/b (blue/green) | deploys or you somehow reload the content inside the | container?! everything that needs special tooling. | mamcx wrote: | You don't always need "no downtime deployments", few | minutes are tolerated in many environments (I work in | enterprise software, where it could be days!). | | Backups? You only need backups or the Db, and that have | zero impact in the use of docker or not* | | *ie: I know what very complex setups the micro-service crow | use for serve their smalls-size disruptive app. I still | think cron + pg_dump + rsync is more than enough... | merb wrote: | well I'm asking because I have a docker-compose file and | I use kustomize+kompose on it, because volume backup is a | thing and the file comes from an upstream vendor and we | can actually miss a few minutes/hours/days of uptime, but | since the databases also use compose and sadly in a way | that I can't remove it (migrate.sh script that makes use | of compose commands), else I can use my kustomize+kompose | setup which basically replaces the kustomize+kompose with | a custom init container that I built, however everytime | they change their shell scripts I need to fix my stuff... | but they say that I should just backup my whole volume/vm | via lvm snapshots or via vmware whatever. which I find a | little bit akward and I do not want to backup my data | with disk snapshots. another way would be to natively | backup stuff via compose, but they use many databases and | it's way harder than just use velero. | mhuffman wrote: | Another one here! I use docker-compose, normal periodic DB | backups to S3 and a twilio script that can use a lambda | function to reload the entire system or parts of it by | simple phone commands when necessary. Site does millions of | views per day. | lmeyerov wrote: | We've been doing this because alternatives like k8s burned | out time, $, and other team members, and our on-prem | customers like it operationally vs k8s. SW teams ran high | uptime stuff before k8s, and you can still do most of those | tricks. We're revisiting, but selectively and only b/c | we're now getting into trickier scenarios like multi-az and | potentially elastic GPUs for our SaaS offering | | Ex: | | - blue/green stateless nodes | | - DNS/load balancer pointer flips | | - Do the DB as a managed saas in the cloud and only ^^^ for | app servers | | - Backups: We've been simply syncing (rsync, pg_dump, ..) | w/ basic backup testing as part of our launch flow | (stressed as part of blue/green flow), and cloud services | automate blob backups. We're moving to DBaaS for doing that | better, which involves taking the DB out of our app for our | SaaS users | | In practice, our service availability has been largely | degraded by external infra factors, like Azure's DNS going | down, than by not using k8s/swarms for internal infra. | Likewise, our own logic bugs causing QoS issues that don't | show up in our 9's reports. | zmmmmm wrote: | > What do you hand a docker-compose file off to in production | | Why hand it off to anything? | | > When would you choose this path over a separate system to | provision your production resources | | When you have a simple system with modest availability | requirements and you don't like unnecessary complexity. ___________________________________________________________________ (page generated 2021-06-01 23:00 UTC)