7 ms·
> Run your applications in Docker from day 1 (with docker-compose it’s as valuable for dev as it is for production) and think carefully before letting your appl
by gravypod 6y ago
> Run your applications in Docker from day 1 (with docker-compose it’s as valuable for dev as it is for production) and think carefully before letting your applications store local state.
I think this is the key take away for many startups. Get it so you:
1. Have a single-command way to bring up your entire backend
2. That command can run on your dev machine
3. You document all of the settings for your containers and deps
Once you have that in a docker-compose.yml file migrating to something like kube when you need health checks, autoscaling, etc is easy.
The only thing you must be critical of is bashing people over the head to make everything you run in your company run in this environment you've created. No special deployments. Establish 1 method with 1 tool and go from there.
Every company I've worked at I've brought a single command `docker-compose up -d` workflow and people were amazed by the productivity gains. No more remembering ports (container_name.local.company.com), no more chasing down configuration files and examples, no more talking to shared DBs, etc.
- thom 6y agoCan I ask people who _don't_ use Kubernetes and maybe have architectures built on proprietary cloud services: how do you manage this?
- gravypod 6y agoDepends on what cloud services you use. I am very opposed to using any cloud service that I can't self host in some way or another. That's a sure fire way to end up screwed. The main cloud services I use at work are: 1. S3/Azure Blob Store 2. DocumentDB/CosmoDB/Cloud Atlas 3. Aurora/A for PG DB 4. ElastiCache/some complex name in azure All of these data stores can be hosted locally using minio for s3, MongoDB for the mongo implementations, and postgres/mysql for the RDBMSs, redis/memcached for ElastiCache. If there was ever a case that I needed to ever use a real - full vendor lockin - solution I would hide it behind an API of my own and configure that API to store data locally. For example, the Azure Blob Store local container is completely broken for any sensible usage and I've been on an github issue thread for ~3 months waiting for them to resolve the issue (you're forced to link your netns to that container to talk to it as the application clients only works over 127.0.0.1). So essentially I have the following settings: - SERVICE_STORAGE_DRIVER=azure/fs - SERVICE_FS_LOCATION=/data - SERVICE_AZURE_CONTAINER=.... - SERVICE_AZURE_....=.... So in development it runs in fs mode, in prod it runs in azure mode, you mock the azure blob client in unit test to make sure that code works.
- IggleSniggle 6y agoBaroque organically grown scripts of arcana.
- pc86 6y agoThis is the correct answer for 99% of brownfield projects, especially those that didn't begin life on a cloud provider.
- RaitoBezarius 6y agoImmutable infrastructure using Nix/NixOS.
- lallysingh 6y agoI have used this. It has its benefits but you have to be ready to walk into alpha-ville (alpha-quality stuff) and take the pain that comes with it. NixOS, however, I will not recommend as your dev environment. Use a regular distro and use NixOS for your containers.
- deleted 6y ago[deleted]
- brian_herman 6y agoI use a git repo and pull in the changes to an ec2 instance. We also use git repos for our lambda functions.
- brian_herman 6y agoAlso our lambda functions are managed by bash scripts we created to interact with aws cli.
- daralthus 6y agoUse Pulumi or Terraform.
- drran 6y agoEverything is packages in RPM, so simple dnf install on bare metal or in container is enough.
- tootie 6y agoAsk every enterprise that existed prior to 2018? Even for small and mid-size enterprises, manual deploys aren't that huge of a deal. Automation with some bash scripts can get you pretty far. Especially if you're only managing a monolith or two. I've worked in some platforms that absolutely defied automation due to their proprietary nature. It just meant that we'd need a few people to spend 1-2 hours every two weeks to run a deployment. That cost added up over even a year or two is probably less than paying for a redesign and replatform. I've also done deploys just using managed services like ECS/Fargate or Heroku where we just build an artifact and push it to the host with a script. A stack that's a load balancer, stateless app server then a DB and/or file store can be provisioned manually once then not really worried about for a long time.
- thom 6y agoTo be clear, I was more asking how people achieve the sort of fast bootstrapped dev environments the parent comment describes using k8s, especially where you’re not necessarily talking about simple topologies like a monolith plus a database.
- AlphaSite 6y agoTilt is pretty great for dev workflows on k8s, they have affordances for debuggers, fast restarts without a full docker build, docker push, k8s delete pod workflow. https://tilt.dev https://tilt.dev
- peterwwillis 6y agoOption 1: Everyone develops on the CI/CD platform. Ops gives devs "disposable environments" to do their testing in. Basically, GitHub + Jenkins + Terraform + AWS. I've used this to stand up real infrastructure every time a PR is opened, and pipelines run against the infra. Code and infra match each other because they both exist in the same branch/repo (monorepo; you can of course do multi-repo, just takes more coordination). It's all destroyed as soon as the PR is closed, but you can also keep it up to do dev work against. You can also keep one copy of the latest master branch up at all times (the "dev" or "cert" or "test" infrastructure) as a shared test environment. Downside: you have to have access to the network (which is in AWS, so that's not so difficult). Upside: the dev environment always mimics production, devs don't need to do anything to stand it up. Option 2: A bunch of mocks, and scripts to stand up stuff in Docker, using docker-compose or something else. This becomes a bit of a problem to manage with lots of devs, though, and docker-compose is not a good model for production deployments.
- what-the-grump 6y agoDefine the same scripted startup on whatever floats you boat and run it. We used to be able clone 400 VMs in 1 hour, sanitize all customer data and refresh a full dev environment from m prod in an hour. TBs of data. But let's all stand around and claim k8s is not your flavor of the day solution to a very old problem, but one that caries a huge amount of complexity and so much network effry that it scares the pants off most people.
- save_ferris 6y ago> people were amazed by the productivity gains Yeah, docker compose is great for running distributed apps locally when everything “just works”. The problem is that it also impedes development when the compose setup isn’t fully optimized. I work on dockerized rails apps, and whenever a new dependency is added, it can take 15 minutes to rebuild the image, which completely breaks my flow. Docker also creates a ton of data bloat locally, requiring me to run docker system prune pretty regularly. Setting up a dependency cache isn’t completely straightforward either. I still think docker compose is worth it, but it’s a deceptively complex beast to get right, and most companies I’ve worked for don’t take the time to get it absolutely right. There’s definitely a cost to using it that people tend to overlook.
- gravypod 6y agoAt my current company, since I'm using gRPC, the build contexts for my containers are annoyingly large and I'm definitely feeling this. It's a massive pain and really annoys me but If I had to choose between 40 minutes of stressful debugging of someone else's config files vs 40 minutes of waiting for a command to finish, I'd take the latter. Long term I'm planning on moving these builds to bazel and taking advantage of incremental builds for my entire monorepo. I'm in the final stages and just validating some stuff is in place before I do that. In the short term I've mitigated this by adding in heavy unit test coverage. Backend devs can basically run the unit tests for most services and are confident the service is working as expected and also enforces any/all security/auth checks. When developing I don't even start up the containers. I boot them up once at the end just to check my work.
- austinpena 6y agoWhy not just have a shared volume for your dependencies? That way nothing needs to rebuild. Then just have a different Docker-compose config for prod
- gravypod 6y agoThe main reasons are: 1. My applications have no dynamic "linking" 2. The containers are distroless 3. Services can be built independently 4. I run the same exact sha in dev/staging/prod To do what you're suggesting would require giving up one of my features which for me is not worth the trade off of a one-time setup 40min build of 20+ services (~2min/service). The last time I paid that 40min cost was ~2 months ago when I reformatted my hard drive. The better solution for me is looking into a build system that can support my different language and tooling choices which happens to be things like Blaze (Bazel/Pants/Buck/Please).
- JamesSwift 6y agoI prefer to take it one abstraction further and setup a makefile where the default `make` brings up the app. This makes it so you can rework the runtime as you see fit and nothing changes. It also doesn't require you to jump into docker immediately, and gives a good extension point for various 'helper script' workflows that you will always have.
- gravypod 6y agoMakefiles are nice in theory but don't scale well to team members who don't know how to use make. If your team is full of experienced C/C++ devs then this will probably work great for you. If you are working with a bunch of android/javascript/etc developers who've never seen make, and who haven't exercised the skillset of reading through 3-decade-old email threads to find answers, you'll find that the only thing you'll do is "make" them upset.
- JamesSwift 6y agoDont these issues also apply to the docker-compose alternative? I'm recommending make as "the one tool" to use for all of your teams apps. No matter what app they work on, everything is setup with `make bootstrap` and everything is run with `make up`. Everything is deployed with `make deploy`. They dont need to understand the _how_, only the _what_.
- gravypod 6y agoNo, other tools do not suffer from what makes make complex. Make is "hard" because of a few things: 1. The syntax is very complex 2. It's just a wrapper around shell command execution 3. There's no single standard everyone fully implements If I implemented a makefile then I'd have to make sure it's compatible with MacOS and GNU Make. The syntax for make files and target deps are also very complex "Do I want to use % or $ or @?" Make also implements very few pieces of functionality. It forks out SHELL for most things and because of this you need to have everything your makefile is using installed on your system. If you have a makefile, invariably, someone implements some tool that's super helpful and works.... until it doesn't. It depends on some system configuration or utility that is no longer a dep of something you've manually installed and the makefile breaks. If you use containers for all of your functionality this is no longer an issue because you can vendor base layers of OSs/images and make sure they don't break. You can also test these changes, that could be breaking, without rolling out to other developers. I cannot test if my Makefile will run on a developer's mac if I don't have a mac myself and even then it's a crap shoot (do they have homebrew? is their PATH correct? etc).
- abatilo 6y agoThere are a lot of projects these days that aim to use Kubernetes as a docker-compose environment. I personally use http://skaffold.dev/ http://skaffold.dev/ with either a local Kubernetes cluster built with https://github.com/rancher/k3d https://github.com/rancher/k3d or https://github.com/kubernetes-sigs/kind https://github.com/kubernetes-sigs/kind. I think there's a very easy argument to be made that says that running K8s locally is overkill, but what I will say is that if you run your applications locally in K8s, that's one step closer to having your local environment mirror the production environment. Couple that with things like running https://github.com/localstack/localstack https://github.com/localstack/localstack locally and you get even closer.
- gravypod 6y ago`kind` and `k3d` are great but I don't think their aimed at being a developer friendly cluster from what I understand. They both require a lot of tweaking and setup to make them look like their a managed kube cluster (LB, storage, ingresses, etc). I wish there was something that could create a kube cluster that: 1. sets up automatic port forwards to my host system 2. handles ingresses by binding port :80 on my system 3. provisions PVs for you when you create PVCs and respects retention policies 4. Allows you to select from a monitoring stack and only require that you supply configurations for dashboards/alerts that can be 1:1 applicable to production so devs can debug dashboards/alerts locally. `kind` is targeting itself as being "a real kubernetes implementation" `k3d` is targeting itself as being Rancher's kubernetes implementation so if you buy into all of the Rancher tooling it'd be a great option.
- MichaelMoser123 6y agoI have a script that simplifies creation of kind clusters with local registry and ingress https://github.com/MoserMichael/kind-helper https://github.com/MoserMichael/kind-helper (to make it more developer friendly that is) but i guess kind is more for automation testing purposes as it runs all modes in docker containers on the same machine.
- gravypod 6y ago
- weedpeg 6y agoAgreed with all mentioned upsides of dockerzing apps. One disadvantage though is a lot of additional work is required for APM/logs/infra monitoring. Even in 2020, newrelic/datadog/others documentation seems to be written non-containerised setup.
- halbritt 6y agoThis facilitates a benefit that I think has been described as "self-contained systems". There's one website on the topic, that imho is too narrowly focused and seeks to distinguish itself from microservices incorrectly, I think. That said, a self-contained system in the context of a container orchestration framework, docker-compose, kubernetes, etc, facilitates an number of benefits, not the least of which is the ease of scaling engineering staff. For example, in typical organizations that claim to have modern development practices, there are static dev, test, and staging environments for a given service. Obviously these are subject to config skew, etc. and must be time-shared between folks. When it's a simple task to create an environment per engineer for each purpose or any other, that can accelerate development tremendously. There are other benefits around resilience in production, but that's another topic entirely.
- pc86 6y agoI would love to see an example of how to set something like this up if you've got any links in mind. We've got multiple apps deployed various ways, everything from pseudo-automated CI/CD (auto build but manual deploy) to fully manual deployment directly out of our IDE. Nothing set up within Docker containers yet except for a few proofs of concept.
- dajohnson89 6y agois there a performance hit with using databases inside docker?
- lazyant 6y agoyes, but due to docker networking overhead (supposing you are using a volume on the host, as you should).
- ravedave5 6y agoHow do you develop/IDE/debug apps like this though?
- gravypod 6y agoMultiple approaches I've seen in the past. My most recent approach is to rely heavily on unit tests and do 99% of your testing there. Before opening a PR/MR/CL into `master` I test my feature out end-to-end using `docker-compose up --build service_name` and make API calls or use the UI to test everything. Code coverage keeps my confident that everything works, my tests automatically run on all other engineer's machines, I can test the code in a very-close-to-prod environment, life is good. Another approach, from a previous startup, who mainly/only used PHP was to volume mount the code you were editing into the containers that were running and to expose an xdebug port for our IDEs to connect to. This was very hacky and error prone but when it worked it worked. Something that I plan to do in the future is to setup some incremental build system that can build all of my software and use that to build my containers. Whenever these outputs change I'll have them redeploy the container in docker-compose or minikube. This way I get very fast builds, very small containers, and much fewer hacks.
- JaggedNZ 6y agoAnyone encountered issues running a docker-compose stack of 5+ containers mostly RoRails apps incl. Postgres on Mac Catalina? Most of the issues seem to be with Postgres DB connections, but it makes starting up our backend painfully slow...
- mattacular 6y agoDocker is slow on Mac. Especially with volumes. This is one drawback to dev'ing everything with Docker locally. If you need to coordinate lots of services across containers to establish the local environment though this is probably something you can live with compared to the alternatives. Edit: Some tuning options also exist - https://docs.docker.com/docker-for-mac/osxfs-caching/ https://docs.docker.com/docker-for-mac/osxfs-caching/
- akritrime 6y agoHow do you make sure it is available on container_name.local.company.com whenever a new container is added?
- gravypod 6y agoYou can setup wildcard DNS names or use `{STAR}.{localhost,local}` for local development. Just use a reverse proxy on `:80` that allows you to define wildcard subdomains like `container_name.{STAR}` or setup the reverse proxy to automatically take the subdomain and use that as the backend server name (should be possible in nginx). HN uses * for formatting so it's been replaced with {STAR}