I knew I needed to quit my job when I first saw the EC2 API. Seeing a few lines of code provision a massive network compelled me to drop what I had been doing and get involved. In the years since that moment, functional approaches have simplified application development. Meanwhile, our approach to deployment is still weighed down with complex state management. Where are our immutable networks? Our lambda cloud calculus? Our functional operations?
Just as functional programming rids us of the unnecessary state that complicates the maintenance of our code, functional operations rids us of the upgrading, quiescing, and process replacement that complicates so much infrastructure automation and deployment code. We intend our running network to be a function of our git repositories, with as few side effects and state transitions as possible.
At Swipely, we assemble running networks as functions of Docker container images, which we build as functions of git repositories. We declare each function and use it to build the output from the input from scratch, firing up new instances running freshly-built containers every time we deploy code, several times a day.
If you want to try Docker, or if you use AWS, then you can use our tools to reliably and repeatably build and deploy networks from your code.
First, use dockly to express your Docker container as a function of your git repo:
deb :my_package do package_name 'myapp' docker do name 'my_image' import 's3://.../base-image.tar.gz' git_archive '/path/to/myapp' build <<-EOF run cd /path/to/myapp && ./configure && make EOF end foreman do name 'myapp' log_dir '/data/logs/myapp' user 'appuser' end end
Now you can package Docker containers with
dockly build my_package. Use your CI environment to build a deployable container whenever you check in code.
Next, use aerosol -- which we're open-sourcing today -- to express your network as a function of your Docker image:
deploy :production_myapp do ssh :production_myapp auto_scaling :production_myapp stop_command 'sudo stop myapp' live_check '/version' app_port 14000 post_deploy_command 'bundle exec rake honeybadger:deploy TO=production' end ssh :production_myapp do user 'aerosol' end auto_scaling :production_myapp do availability_zones ['us-east-1a', 'us-east-1b'] min_size 2 max_size 2 launch_configuration :production_myapp tag 'Name' => 'prod-myapp' end launch_configuration :production_myapp do instance_type 'm1.large' ami 'ami-90374bf9' iam_role 'role-prod-myapp' key_name 'prod-myapp' security_groups ['prod-myapp', 'prod-ssh'] user_data ERB.new(File.read('startup.sh.erb')).result(binding) # include install of Docker image end
Now deploy and cut over to a brand new network with
aerosol deploy production_myapp.
Finally, get the humans involved in whatever way best suits your development cycle and culture. At Swipely, we wrote a Hubot plugin to kick off and coordinate production deploys over HipChat: