wine tradition of more than 8000 years (Google it) • UNESCO honors the cultural significance of the Georgian alphabet • Come to visit Georgia! (მობრძანდით საქართველოში!)
Delivering changes to production is often a bottleneck of the development process • Heroku, Fly.io and Render give an excellent developer experience, but cost you premium • Hosted Kubernetes on AWS, GCP, Digital Ocean lock you to the vendor and cost you premium • More complex infrastructure solutions require more engineers in your team
application server (e.g. Puma phased restart) Docker • Run Docker commands ◦ Start new container and wait until it is healthy ◦ Notify the proxy server about the new container ◦ Tell the proxy server to stop routing requests for the old container ◦ Stop old container
almost perfect solution, doesn’t it? 1. Docker-ready 2. Declarative configuration ◦ Uses Docker labels to define routing 3. Automatic routing ◦ Traffic to the new container is routed automatically 4. Self-healing ◦ If the container restarts, Traefik dynamically updates routing
“old” is running. 2. Wait for the “new” to become healthy 3. “Tell” Traefik to stop routing requests to the “old” 4. Wait while Traefik will actually stop routing to the “old” container 5. Stop the “old” container. But Docker container’s labels are immutable and Traefik is declarative, we cannot “tell” him anything.
file on the host 2. Start the “new” container, mounting the cord file into /tmp and including a check for the file in the docker health check 3. Wait for the “new” to become healthy 4. Delete the health check file (“cut the cord”) for the “old” container 5. Wait for it to become unhealthy and give Traefik a couple of seconds to notice 6. Stop the “old” container
Has Let’s Encrypt built-in • Imperative `kamal-proxy deploy onetribe-pghero --target c67f2259dce6:8080 --host pghero.onetribe.team --tls` The command above will wait until the host is provisioned and the container is healthy. There also are `kamal-proxy remove`, `kamal-proxy list`, etc.
not (yet?) supported • Distributed as a gem (gem “thruster”) • Easy to run (“./bin/thrust ./bin/rails server”) • Handles: ◦ Serving static files with “X-Sendfile” support ◦ Caching of public assets ◦ Compression
it is missing • No fail2ban, no firewall, hardening is a must! • DO NOT EXPOSE the Docker daemon on port 2375 If you are using Ansible – https://github.com/dev-sec/ansible-collection-hardening
with terminology: • Container • Image • Registry Have any questions? User Docker docs. https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-a-conta iner/
registry (at least for now) • Every deploy – the new image is built, pushed and pulled • ghcr.io, Docker Hub, ECR, DigitalOcean Container Registry, • You will pay for the traffic
build images locally • I insist you to use Kamal as a CD workflow instead: ◦ Your architecture can be different from the architecture you deploy to ◦ Usually ARM64 locally vs x86-64 on the server (we all love Mac). ◦ Your internet connection may be slow and not stable (like in the hotel, here) • Kamal integrates well with any CI/CD platform: GH Actions, GitLab CI, BitBucket Pipeline If you are on GitHub Actions – https://github.com/igor-alexandrov/kamal-github-actions
– use composite actions • Don’t reinvent a bicycle, use existing actions e.g., ◦ https://github.com/webfactory/ssh-agent ◦ https://github.com/ruby/setup-ruby Use Kamal as an action too – https://github.com/igor-alexandrov/kamal-deploy
`.kamal/secrets` • Two options that are suitable for a production usage: ◦ Store secrets in GitHub Secrets and substitute them from environmental variables ◦ Store secrets in a password manager • I love the first option because of no additional services
the hood • Kamal limits maximum file size to 10 megabytes by default • Don’t forget to choose the right logging driver ◦ json-file (default) ◦ local ◦ awslogs ◦ gcplogs • You should have a log viewer (e.g. CloudWatch, Dozzle, Logdy) https://dozzle.dev OR https://logdy.dev
use case – microservices in a monorepo • Another use case – multi-tenant or multi-region deployments Kamal allows selecting the config file to use ./bin/kamal --config-file ./config/deploy.service1.yml
configure a backup for your database • Don’t forget to set up monitoring • Don’t forget to update your Dockerfile dependencies • Keep your application up to date too • Know what you are doing and have fun!