Skip to content

Instantly share code, notes, and snippets.

@res0nat0r
Forked from maxivak/readme.md
Created January 28, 2019 04:14
Show Gist options
  • Save res0nat0r/e862077d8f95acd66d83310478cb6e35 to your computer and use it in GitHub Desktop.
Save res0nat0r/e862077d8f95acd66d83310478cb6e35 to your computer and use it in GitHub Desktop.
Provisioning Docker containers with Chef

Provisioning Docker container with Chef

Chef provisioning

  • Chef provisioning is a framework that allows clusters to be managed by the chef-client and the Chef server in the same way nodes are managed: with recipes.

  • Chef provisioning is a collection of resources that enable the creation of machines and machine infrastructures using the chef-client.

  • Read more: https://docs.chef.io/provisioning.html

Provision Docker container

We will use Chef provisioning to create a Docker container.

  • It assumes we have chef-repo on the workstation. This chef-repo contains common cookbooks.

  • Also we can have custom cookbooks.

  • Directory structure

our project:

/path/to/project/
    |__ .chef/ - directory with settings for knife
    |__ cookbooks/ - directory with cookbooks for the machine
    |_  mycluster.rb
    |_ destroy.rb
    

chef-repo - somewhere on the workstation

/path/to/chef-repo
    |_ cookbooks
    ...
    
  • create directory .chef in your project

  • create .chef/knife.rb:

log_level                :info
current_dir = File.dirname(__FILE__)

#node_name                "provisioner"
#client_key               "#{current_dir}/dummy.pem"
#validation_client_name   "validator"

cookbook_path [ '/mydata/chef-repo/cookbooks', "#{current_dir}/../cookbooks" ]

include paths to cookbooks from chef-repo and to cookbooks in our project.

  • Create file mycluster.rb:
require 'chef/provisioning'


with_driver 'docker'
machine 'mycontainer' do
  action :converge

  #recipe 'apt::default'
  recipe 'base::default'

  # attributes
  attribute 'base', node['base']
  #attribute 'java', node['java']


  machine_options docker_options: {
      base_image: {
          name: 'ubuntu',
          repository: 'ubuntu',
          tag: '14.04'
      },

      #ENV (Environment Variables)
      #Set any env var in the container by using one or more -e flags, even overriding those already defined by the developer with a Dockerfile ENV
      :env => {
          "deep" => 'purple',
          "led" => 'zeppelin'
      },

      # Ports can be one of two forms:
      # src_port (string or integer) is a pass-through, i.e 8022 or "9933"
      # src:dst (string) is a map from src to dst, i.e "8022:8023" maps 8022 externally to 8023 in the container

      # Example (multiple):
      #:ports => ["9022:22"],

      # Volumes can be one of three forms:
      # src_volume (string) is volume to add to container, i.e. creates new volume inside container at "/tmp"
      # src:dst (string) mounts host's directory src to container's dst, i.e "/tmp:/tmp1" mounts host's directory /tmp to container's /tmp1
      # src:dst:mode (string) mounts host's directory src to container's dst with the specified mount option, i.e "/:/rootfs:ro" mounts read-only host's root (/) folder to container's /rootfs
      # See more details on Docker volumes at https://github.com/docker/docker/blob/master/docs/sources/userguide/dockervolumes.md .

      # Example (single):
      #:volumes => "/tmp",

      # Example (multiple):
      #:volumes => ["/tmp:/tmp", "/:/rootfs:ro"],

      # if you need to keep stdin open (i.e docker run -i)
      # :keep_stdin_open => true

    },
    docker_connection: {
        # optional, default timeout is 600
        #:read_timeout => 1000,
    }

end

It will run two recipes:

  • apt-get update

  • our recipe 'base'

  • Create recipe 'base' in cookbooks

  • cookbooks/base/recipes/default.rb

file '/tmp/1.txt' do
  content "node attributes: #{node['base'].inspect}"
end
  • cookbooks/base/attributes/default.rb - specify default attributes for recipe
default['base']['attr1'] = 'v1'
default['base']['attr2'] = 'v2'

  • attributes in json file
# mymachine.json

{
  "base": {
    "sitename": "mysite.com",
    "opt1": "11",
    "opt2": "22"
  }
}
  • run provisioning
chef-client -z mycluster.rb -j mymachine.json

It will create a new Docker container named 'mycontainer' and run recipes. Recipe base will create a temp file '/tmp/1.txt' with contents. In our example it should contain:

# /tmp/1.txt
node attributes: {"sitename"=>"mysite.com", "opt1"=>"11", "opt2"=>"22"}

Destroy Docker container

  • Create file 'destroy.rb'
require 'chef/provisioning'

machine 'mycontainer' do
  action :destroy
end


  • run
chef-client -z destroy.rb

it will remove Docker container named 'mycontainer'

Example

Test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment