Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Vincit Teatime 2015.2 - Niko Kurtti: SaaSiin pa(i)nostusta


Published on

Modernin ohjelmistoprojektin odotetaan olevan yksikkö- ja integraatiotestattu, koodikattavuuden kartoitettu, muutosten katselmoitu, ja koodin siirtyvän automaattisesti versiohallinnasta ajoon beta- ja tuotantoklustereille. Milloin? No versiohallintaan puskettaessa tietysti. Versiohallintalähtöistä, automoitua lähdekoodin ja tuotteenhallintaa GitHubista Traviksen syövereihin ja ajoon Amazonin Elastic Beanstalkiin. Tule kuulemaan hiljaista tietoa tämän vuosituhannen ohjelmistokehityksen perustyökaluista.

Published in: Technology
  • Login to see the comments

  • Be the first to like this

Vincit Teatime 2015.2 - Niko Kurtti: SaaSiin pa(i)nostusta

  1. 1. Building containers Turbocharged!
  2. 2. Shopify • All the commerce • 165k+ merchants, 8 Billion GMV • 300M+ unique visits/month • 4000+ containers • RoR, MySQL, Redis, Memcache, Elasticsearch, Chef, Go, Podding, Multi-DC,...
  3. 3. Docker at Shopify • Serving production traffic for over a year • Gives developers more freedom (and responsibility) around how applications are being ran • Offers super fast and reliable deploys1 1 When it works. Warstories are plenty
  4. 4. Building containers
  5. 5. Dockerfiles Super simple (Dockerfile is essentially shell commands + a handful of specialized instructions) Super efficient (Detects changes and skips things that have not changed) Super inefficient and complicated for anything nontrivial
  6. 6. Simple, eh? FROM ruby:2.1.3 RUN apt-get update RUN apt-get upgrade RUN apt-get install -qq -y libmysqlclient-dev RUN useradd --create-home rails_is_fun WORKDIR /home/rails_is_fun COPY . /home/rails_is_fun RUN bundle install CMD bundle exec unicorn -p 3000
  8. 8. FROM ruby:2.1.3 RUN apt-get update RUN apt-get upgrade RUN apt-get install -qq -y libmysqlclient-dev RUN useradd --create-home rails_is_fun WORKDIR /home/rails_is_fun COPY Gemfile /home/rails_is_fun/Gemfile COPY Gemfile.lock /home/rails_is_fun/Gemfile.lock RUN bundle install COPY . /home/rails_is_fun CMD bundle exec unicorn -p 3000 Even with this you have no concept of Gem cache, so any changes to Gemfile essentially means building them from scratch Not to mention the burden of apt-get update/upgrade
  9. 9. What about secrets? When building application containers its pretty common to have secrets (API keys, DB urls etc.). Dockerfile doesn't support any temporary/external files. While building you can't use VOLUMES either No real solutions. Everything is bad (secrets in plaintext in layers, external wrappers etc)
  10. 10. #!/bin/bash gem install ejson ejson decrypt config/config.production.ejson > config.json docker build -t rails_is_fun . rm -rf config.json
  11. 11. The things we needed • Performance (not only for building a lot of containers but building a single one quickly) • Security. We handle money and peoples private information, so having a secure system is kinda important • Coordinator for builds
  12. 12. Solution: Write your own builder
  13. 13. Our custom builder Locutus is a Golang app that: • Listens to webhooks (every commit to GH triggers a build) • Builds containers • Pushes to our private registry • Has a webgui showing the build step-by-step • Sends hooks about build statuses • Scales horizontally, eg. we can have N builders
  14. 14. The interesting part, building We replaced Dockerfiles with prepare, precompile and compile scripts (vanilla Bash) These scripts actually represent a different build phase and live in the app repo Each phase does a docker run with the script and saves the container with docker commit.
  15. 15. prepare is used for your system packages (eg. apt-get install libmysqlclient-dev). In this phase we only copy the script itself to our baseimage We cache this image based on the md5sum of the prepare During Shopify builds we really rarely have to run this phase since system level depencies doesn't change often.
  16. 16. precompile is used for application dependencies and asset building (eg. bundle install) Used for creating a folder of wanted artifacts. Only thing that is persisted is /artifacts Run on every build, but build upon the previous cache of the specific app (and branch). So we never end up pulling all gems because of a Gemfile change etc.
  17. 17. compile is used for moving the generated arfifacts to correct folders (eg. .bundle) and finishing setup Run on every build, but super fast since we are just doing bunch of mv and rm (to cleanup caches etc. to slim the image) The result of this phase is the final image we actually can deploy to be run.
  18. 18. Build times around 40-50 seconds thanks to heavy caching Containers never see the keys that are used for decrypting secrets
  19. 19. Questions? ps.