AWS DevOps & Developer Productivity Blog
Running Docker on AWS OpsWorks
Step 1: Create Recipes
case node[:platform] when "ubuntu","debian" package "docker.io" do action :install end when 'centos','redhat','fedora','amazon' package "docker" do action :install end end service "docker" do action :start end |
The docker::docker-deploy recipe deploys your docker containers (specified by a Dockerfile):
include_recipe 'deploy' node[:deploy].each do |application, deploy| if node[:opsworks][:instance][:layers].first != deploy[:environment_variables][:layer] Chef::Log.debug("Skipping deploy::docker application #{application} as it is not deployed to this layer") next end opsworks_deploy_dir do user deploy[:user] group deploy[:group] path deploy[:deploy_to] end opsworks_deploy do deploy_data deploy app application end bash "docker-cleanup" do user "root" code <<-EOH if docker ps | grep #{deploy[:application]}; then docker stop #{deploy[:application]} sleep 3 docker rm #{deploy[:application]} sleep 3 fi if docker images | grep #{deploy[:application]}; then docker rmi #{deploy[:application]} fi EOH end bash "docker-build" do user "root" cwd "#{deploy[:deploy_to]}/current" code <<-EOH docker build -t=#{deploy[:application]} . > #{deploy[:application]}-docker.out EOH end dockerenvs = " " deploy[:environment_variables].each do |key, value| dockerenvs=dockerenvs+" -e "+key+"="+value end bash "docker-run" do user "root" cwd "#{deploy[:deploy_to]}/current" code <<-EOH docker run #{dockerenvs} -p #{node[:opsworks][:instance][:private_ip]}:#{deploy[:environment_variables][:service_port]}:#{deploy[:environment_variables][:container_port]} --name #{deploy[:application]} -d #{deploy[:application]} EOH end end |
Then create a repository to store your Dockerfile. Here’s a sample Dockerfile to get you going:
FROM ubuntu:12.04 RUN apt-get update RUN apt-get install -y nginx zip curl RUN echo "daemon off;" >> /etc/nginx/nginx.conf RUN curl -o /usr/share/nginx/www/master.zip -L https://codeload.github.com/gabrielecirulli/2048/zip/master RUN cd /usr/share/nginx/www/ && unzip master.zip && mv 2048-master/* . && rm -rf 2048-master master.zip EXPOSE 80 CMD ["/usr/sbin/nginx", "-c", "/etc/nginx/nginx.conf"] |
Step 2: Create an OpsWorks Stack
- Select Add a Stack to create an OpsWorks stack.
- Give it a name and select Advanced.
- Set Use custom Chef Cookbooks to Yes.
- Set Repository type to Git.
- Set the Repository URL to the repository where you stored the recipes created in the previous step.
- Click the Add Stack button at the bottom of the page to create the stack.
Step 3: Add a Layer
- Select Add Layer.
- Choose Custom Layer, set the name to “Docker”, shortname to “docker”, and click Add Layer.
- Click the layer’s edit Recipes action and scroll to the Custom Chef recipes section. You will notice there are several headings—Setup, Configure, Deploy, Undeploy, and Shutdown—which correspond to OpsWorks lifecycle events. OpsWorks triggers these events at these key points in instance’s lifecycle, which runs the associated recipes.
- Enter docker::install in the Setup box and click + to add it to the list
- Enter docker::docker-deploy in the Deploy box and click + to add it to the list
- Click the Save button at the bottom to save the updated configuration.
Step 4: Add an Instance
Step 5: Add an App & Deploy
- In the navigation pane, click Apps and on the Apps page, click Add an app.
- On the App page, give it a Name.
- Set app’s type to other.
- Specify the app’s repository type.
- Specify the app’s repository URL. This is where your Dockerfile lives and is usually a separate repository from the cookbook repository specified in step 2.
- Set the following environment variables:
- container_port – Set this variable to the port specified by the EXPOSE parameter in your Dockerfile.
- service_port – Set this variable to the port your container will expose on the instance to the outside world. Note: Be sure that your security groups allow inbound traffic for the port specified in service_port.
- layer – Set this variable to the shortname of the layer that you want this container deployed to (from Step 3). This lets you have multiple docker layers with different apps deployed on each, such as a front-end web app and a back-end worker.
- For our example, set container_port=80, service_port=80, and layer=docker. You can also define additional environment variables that are automatically passed onto your Docker container, for example a database endpoint that your app connects with.
- Keep the default values for the remaining settings and click Add App.
- To install the code on the server, you must deploy the app. It will take some time for your instances to boot up completely. Once they show up as “online” in the Instances view, navigate to Apps and click deploy in the Actions column. If you create multiple docker layers, note that although the deployment defaults to all instances in the stack, the containers will only be deployed to the layer specified in the layer environment variable.
- Once the deployment is complete, you can see your app by clicking the public IP address of the server. You can update your Dockerfile and redeploy at any time.