Platform

AI

AI Agents
Sense, decide, and act faster than ever before
AI Visibility
See how your brand shows up in AI search
AI Feedback
Distill what your customers say they want
Amplitude MCP
Insights from the comfort of your favorite AI tool

Insights

Product Analytics
Understand the full user journey
Marketing Analytics
Get the metrics you need with one line of code
Session Replay
Visualize sessions based on events in your product
Heatmaps
Visualize clicks, scrolls, and engagement

Action

Guides and Surveys
Guide your users and collect feedback
Feature Experimentation
Innovate with personalized product experiences
Web Experimentation
Drive conversion with A/B testing powered by data
Feature Management
Build fast, target easily, and learn as you ship
Activation
Unite data across teams

Data

Warehouse-native Amplitude
Unlock insights from your data warehouse
Data Governance
Complete data you can trust
Security & Privacy
Keep your data secure and compliant
Integrations
Connect Amplitude to hundreds of partners
Solutions
Solutions that drive business results
Deliver customer value and drive business outcomes
Amplitude Solutions →

Industry

Financial Services
Personalize the banking experience
B2B
Maximize product adoption
Media
Identify impactful content
Healthcare
Simplify the digital healthcare experience
Ecommerce
Optimize for transactions

Use Case

Acquisition
Get users hooked from day one
Retention
Understand your customers like no one else
Monetization
Turn behavior into business

Team

Product
Fuel faster growth
Data
Make trusted data accessible
Engineering
Ship faster, learn more
Marketing
Build customers for life
Executive
Power decisions, shape the future

Size

Startups
Free analytics tools for startups
Enterprise
Advanced analytics for scaling businesses
Resources

Learn

Blog
Thought leadership from industry experts
Resource Library
Expertise to guide your growth
Compare
See how we stack up against the competition
Glossary
Learn about analytics, product, and technical terms
Explore Hub
Detailed guides on product and web analytics

Connect

Community
Connect with peers in product analytics
Events
Register for live or virtual events
Customers
Discover why customers love Amplitude
Partners
Accelerate business value through our ecosystem

Support & Services

Customer Help Center
All support resources in one place: policies, customer portal, and request forms
Developer Hub
Integrate and instrument Amplitude
Academy & Training
Become an Amplitude pro
Professional Services
Drive business success with expert guidance and support
Product Updates
See what's new from Amplitude

Tools

Benchmarks
Understand how your product compares
Templates
Kickstart your analysis with custom dashboard templates
Tracking Guides
Learn how to track events and metrics with Amplitude
Maturity Model
Learn more about our digital experience maturity model
Pricing
LoginContact salesGet started

AI

AI AgentsAI VisibilityAI FeedbackAmplitude MCP

Insights

Product AnalyticsMarketing AnalyticsSession ReplayHeatmaps

Action

Guides and SurveysFeature ExperimentationWeb ExperimentationFeature ManagementActivation

Data

Warehouse-native AmplitudeData GovernanceSecurity & PrivacyIntegrations
Amplitude Solutions →

Industry

Financial ServicesB2BMediaHealthcareEcommerce

Use Case

AcquisitionRetentionMonetization

Team

ProductDataEngineeringMarketingExecutive

Size

StartupsEnterprise

Learn

BlogResource LibraryCompareGlossaryExplore Hub

Connect

CommunityEventsCustomersPartners

Support & Services

Customer Help CenterDeveloper HubAcademy & TrainingProfessional ServicesProduct Updates

Tools

BenchmarksTemplatesTracking GuidesMaturity Model
LoginSign Up

Deploying Applications with Docker and Saltstack

This is all that is required to do basic setup, deployment and upgrade of docker containers with saltstack.
Product

Mar 3, 2016

9 min read

Jay Bendon

Jay Bendon

Former Senior Software Engineer, Amplitude

Deploying Applications with Docker and Saltstack

Here at Amplitude we’ve chosen to build and deploy with docker and saltstack. Docker allows us to minimize configuration and customization required to deploy our services. Saltstack is a powerful systems and configuration management tool that is fast, scales well and is highly extendable for solving just about any infrastructure automation or orchestration problem.

How did we choose docker and saltstack?

I’m sure you can imagine a lot of startups start off deploying and building software onto a manually provisioned machine by cloning a git repo and doing the needful. Naturally this process doesn’t scale very far.

First we turned to docker. This for us was a no brainer considering the speed and repeatability of builds we’ve achieved using docker containers for our services. Once we knew we were going to be building with docker we went on a search for a systems and configuration management tools to make our lives easier.

First a few service deployments were rolled out using a tool called Ansible. Ansible was great for getting off the ground quickly but it didn’t take long for us to notice things slowing down and more complex logic being difficult to maintain as we scaled. We took some time to review our options to us. Chef was a strong candidate especially due to its widespread adoption, strong testing capabilities, simplicity and depth of use, but ultimately we chose Saltstack.

Why? Well, first we are mostly a java and python shop, so being able to write python for systems and configuration management was a huge plus to the team. Security was another concern for us. Saltstack allows us to provide pub/priv keys for all masters and minions guaranteeing their authenticity and providing a secure channel for master/minion communications without sacrificing performance or scalability.

Saltstack’s commitment to docker was very promising.

At the time we started using salt they were using the docker-io module and after community feedback realised there were a lot of improvements available and was worth building an entirely new module to address these concerns. Saltstack has an excellent community. I have been able to provide and receive help readily in the community. Bug reports, feature requests and pull-requests are responded to very quickly, usually on the order of 24 hours, although admittedly some bigger bugs have taken some more time to be resolved.

Salt Docker

Getting started with docker and saltstack is pretty easy. We will assume that setting up the salt master and minions is already done. This information is written for use with the docker-io module, which is still the default docker module for salt, but has been deprecated in favor of the newer docker-ng module. The code examples are written to use the python renderer available for saltstack.

Setup docker dependencies using saltstack. You will want to install python-pip, docker-py, lxc-docker and ensure the docker service is running on nodes you want to deploy docker containers on.

Pulling your first container

nginx.sls

#!py def run(): config = {} config['nginx_pulled'] = { 'docker.pulled': [ {'name': ‘nginx’}, # docker repository {'tag': “latest”}, {'force': True}, # force pull image {'require': [ {'pip': 'docker-py'} # require that docker-py is installed by pip ]}, {'order': 200} # optional strict ordering of salt operations ] } return config

Installing the container

nginx.sls

config['ournginx_container'] = { 'docker.installed': [ {'name': “ournginx”}, {'image': “nginx:latest”}, {'mem_limit': None}, # workaround for https://github.com/saltstack/salt/issues/25492 {'require': [ {'docker': 'nginx_pulled'}, # require image is pulled ]}, {'order': 210} ] }

Running the container

nginx.sls

config['ournginx_running'] = { 'docker.running’: [ {'name': “ournginx”}, {'image': “nginx:latest”}, {'require': [ {'docker': 'ournginx_container'}, ]}, {'order': 211} ] }

One caveat to note, the above install and running states should have identical options where applicable. If you set up any environment variables or volumes be sure to configure it for both docker.installed and docker.running.

Now that handles the bare minimum required to pull and deploy a container. But what happens if we release a new “latest” container for nginx? Well, it will pull the latest container, but the running and installed containers will not be updated. Lets fix that. nginx.sls

config['ournginx_absent'] = { 'cmd.run': [ {'name': '/usr/bin/docker stop -t 10 ournginx && /usr/bin/docker rm -f ournginx'}, {'unless': '/usr/local/bin/docker_compare_running ournginx nginx:latest‘}, {'require': [{'file': 'docker_compare_running'}]}, {'order': 201} ] }

docker_compare_running

#!/bin/bash # Script should return 0 if container is not running, insufficient args, or # downloaded container vs running container is not different. # Return 1 if running container is different. if [ $# -lt 2 ];then echo "Please provide a image to search" # return 0 so salt doesn't think the images are different exit 0 fi # return 0 if container not running if [ $(/usr/bin/docker ps --filter name=$1 -q |wc -l) -eq 0 ];then exit 0 fi # return >0 if containers do not match. /usr/bin/docker inspect --format "{{ .Image }}" $1 |grep $(/usr/bin/docker inspect --format "{{ .Id }}" $2)

Great, now when we release a new version of the nginx container, we will stop and remove the old container allowing the updated container to be relaunched.

All of this is great so far, but if you’re setting this up to deploy from a private docker registry or repo, you will need a way to authenticate. The docker modules support the docker v1 registry api. All that is necessary to enable pulling from private repository or registry is configuration of docker-registries pillar data which is just a map of the repository to the username, email and password with access.

Our default pillar data: init.sls

#!py def run(): base_pillar = {} base_pillar['docker-registries'] = { 'https://index.docker.io/v1/': { 'email': 'devops@amplitude.com', 'password': “docker-registry-password”, 'username': ‘accountname' } } return base_pillar

That’s all that is required to do basic setup, deployment and upgrade of docker containers with saltstack. We chose to write our salt states in python as it allowed us to have some more complex states while still maintaining as much readability as possible compared to yaml state files. Most of our docker deployments were born out of these basic steps. There is still a lot of room for improvement based on your specific needs.

A few things that can be helpful or improved upon:

  • Using pillar values to explicitly gate the container or containers deployed.
  • Deploying new containers alongside old for a seamless deployment.
  • Container rollbacks.
  • Upgrade to dockerng
  • A custom state or module to reduce boilerplate required for deploying docker containers with saltstack.
  • Scale number or size of containers based on host specs

Comments

Kevin Audleman: Does your method of stopping the nginx container then spinning up a new one result in downtime?

Jay Bendon: Yes, if you’re only running a single instance of NGINX, or don’t have health-check based load-balancing and you are reloading all the containers at once there will be potential for end user to experience unavailability. NGINX does handle the shutdown signal which causes it finish processing in-flight requests before terminating the process without accepting any new connections and our load-balancers detect the NGINX instance is going out of rotation and remove it from the pool during the reload of the container and we never release all of our containers at the same time so the transition is un-detected by the end user. You do want to make sure you’re shutdown timeout is long enough for your requests to finish processing otherwise they may be terminated in-flight.

About the author
Jay Bendon

Jay Bendon

Former Senior Software Engineer, Amplitude

More from Jay

Jay Bendon is a former Senior DevOps Engineer at Amplitude. He focuses on ensuring Amplitude engineers have the tools, insights and guidance necessary to operate reliably while scaling for growth. He was previously part of Google, Amazon, and Ooyala engineering organizations.

More from Jay
Topics
Platform
  • Product Analytics
  • Feature Experimentation
  • Feature Management
  • Web Analytics
  • Web Experimentation
  • Session Replay
  • Activation
  • Guides and Surveys
  • AI Agents
  • AI Visibility
  • AI Feedback
  • Amplitude MCP
Compare us
  • Adobe
  • Google Analytics
  • Mixpanel
  • Heap
  • Optimizely
  • Fullstory
  • Pendo
Resources
  • Resource Library
  • Blog
  • Product Updates
  • Amp Champs
  • Amplitude Academy
  • Events
  • Glossary
Partners & Support
  • Contact Us
  • Customer Help Center
  • Community
  • Developer Docs
  • Find a Partner
  • Become an affiliate
Company
  • About Us
  • Careers
  • Press & News
  • Investor Relations
  • Diversity, Equity & Inclusion
Terms of ServicePrivacy NoticeAcceptable Use PolicyLegal
EnglishJapanese (日本語)Korean (한국어)Español (Spain)Português (Brasil)Português (Portugal)FrançaisDeutsch
© 2025 Amplitude, Inc. All rights reserved. Amplitude is a registered trademark of Amplitude, Inc.

Recommended Reading

article card image
Read 
Insights
The Product Benchmarks Every Media and Entertainment Company Should Know

Dec 23, 2025

5 min read

article card image
Read 
Customers
Amplitude Pathfinder: Why Austin Costello is a Triple Threat Analyst

Dec 22, 2025

8 min read

article card image
Read 
Product
Introducing Amplitude on Amplitude

Dec 22, 2025

3 min read

article card image
Read 
Insights
Stop Asking, Start Listening: How to Connect Feedback to Behavior

Dec 19, 2025

12 min read

Explore Related Content

Integration
Using Behavioral Analytics for Growth with the Amplitude App on HubSpot

Jun 17, 2024

10 min read

Personalization
Identity Resolution: The Secret to a 360-Degree Customer View

Feb 16, 2024

10 min read

Product
Inside Warehouse-native Amplitude: A Technical Deep Dive

Jun 27, 2023

15 min read

Guide
5 Proven Strategies to Boost Customer Engagement

Jul 12, 2023

Video
Designing High-Impact Experiments

May 13, 2024

Startup
9 Direct-to-consumer Marketing Tactics to Accelerate Ecommerce Growth

Feb 20, 2024

10 min read

Growth
Leveraging Analytics to Achieve Product-Market Fit

Jul 20, 2023

10 min read

Product
iFood Serves Up 54% More Checkouts with Error Message Makeover

Oct 7, 2024

9 min read

Blog
InsightsProductCompanyCustomers
Topics

101

AI

APJ

Acquisition

Adobe Analytics

Amplify

Amplitude Academy

Amplitude Activation

Amplitude Analytics

Amplitude Audiences

Amplitude Community

Amplitude Feature Experimentation

Amplitude Guides and Surveys

Amplitude Heatmaps

Amplitude Made Easy

Amplitude Session Replay

Amplitude Web Experimentation

Amplitude on Amplitude

Analytics

B2B SaaS

Behavioral Analytics

Benchmarks

Churn Analysis

Cohort Analysis

Collaboration

Consolidation

Conversion

Customer Experience

Customer Lifetime Value

DEI

Data

Data Governance

Data Management

Data Tables

Digital Experience Maturity

Digital Native

Digital Transformer

EMEA

Ecommerce

Employee Resource Group

Engagement

Event Tracking

Experimentation

Feature Adoption

Financial Services

Funnel Analysis

Getting Started

Google Analytics

Growth

Healthcare

How I Amplitude

Implementation

Integration

LATAM

Life at Amplitude

MCP

Machine Learning

Marketing Analytics

Media and Entertainment

Metrics

Modern Data Series

Monetization

Next Gen Builders

North Star Metric

Partnerships

Personalization

Pioneer Awards

Privacy

Product 50

Product Analytics

Product Design

Product Management

Product Releases

Product Strategy

Product-Led Growth

Recap

Retention

Startup

Tech Stack

The Ampys

Warehouse-native Amplitude