Use Chef Zero in Dockerfile to Build Image with a Chef Cookbook

From Bonus Bits
Jump to: navigation, search


This article gives an example of how a Dockerfile can be written to use Chef Zero to build the image from a cookbook!


  • Docker Installed
  • Chef cookbook


  • Docker for Mac v17.07.0-ce-rc4-mac25 (18986)
  • macOS v10.12.6
  • ChefDK v1.6.1
  • Amazon Linux latest base image (766ebb052d4f)
  • Chef Zero
  • Install ChefDK 1.6.1 on image build
    • Using ChefDK over Chef Client because it has Chef Client and several other default gems such as Berkshelf and Inspec.

Create Test Directories

To make the example code work as is you'll need a few directories off the root of your cookbook. I recommend at least having an environment file. You can remove the role and obviously don't need data bags. Although, it is set to copy from the directory. So either just create the directory or remove the COPY command. Also, the encrypted_data_bag_secret is not required. Just giving my layout example in case you're interested. Although, you'll need to comment/remove from client.rb. I could just be a blank file (touch encrypted_data_bag_secret) etc.

├── data_bags
│   ├── cookbook_name
│   │   ├── data_bag_item.json
│   └── encrypted_data_bag_secret
├── environments
│   ├── environment.json
├── node
│   └── client.rb
└── roles
    └── role.json

Create Client.rb

  1. Create a client.rb here test/node/client.rb.
    node_name 'docker_node'
    checksum_path '/opt/chef-repo/checksums'
    file_cache_path '/opt/chef-repo/cache'
    file_backup_path '/opt/chef-repo/backup'
    cookbook_path '/opt/chef-repo/cookbooks'
    data_bag_path '/opt/chef-repo/data_bags'
    environment_path '/opt/chef-repo/environments'
    role_path '/opt/chef-repo/roles'
    chef_server_url ''
    encrypted_data_bag_secret '/opt/chef-repo/data_bags/encrypted_data_bag_secret'
    log_level :info
    log_location '/var/log/chef-client.log'
    verify_api_cert false

Create Dockerfile

  1. Create a Dockerfile in the root of your cookbook something like the following. Replace' cookbook_name with your cookbook name.
    FROM amazonlinux:latest
    MAINTAINER Levon Becker ""
    LABEL version="2.1.10" \
          description="Amazon Linux Image built using Chef Zero Example." \
          github="" \
    # Build Cookbook Args
    # Chef Client v12.21.4
    ARG chefdk_version=1.6.1
    ARG cookbook_name=cookbook_name
    ARG chef_role=role
    ARG chef_environment=environment
    ARG chef_config_path=/opt/chef-repo
    # Install Bootstrap Packages
    RUN yum clean all
    RUN yum update -y --exclude=kernel*
    RUN yum install -y git htop mlocate net-tools openssh-client openssh-server procps upstart util-linux vim-enhanced which
    # Install ChefDK
    RUN curl -L | bash -s -- -P chefdk -v ${chefdk_version}
    # Setup Chef Client
    RUN mkdir -p ${chef_config_path}
    WORKDIR ${chef_config_path}
    RUN mkdir -p cookbooks checksums environments cache backup data_bags roles
    RUN mkdir cookbooks/${cookbook_name}
    COPY . cookbooks/${cookbook_name}/
    COPY test/roles/* roles/
    COPY test/environments/* environments/
    COPY test/data_bags/* data_bags/
    COPY test/node/client.rb ${chef_config_path}/client.rb
    # Download Dependant Cookbooks
    WORKDIR ${chef_config_path}/cookbooks/${cookbook_name}
    RUN /opt/chefdk/bin/berks install
    RUN /opt/chefdk/bin/berks vendor ${chef_config_path}/cookbooks/
    # Run Chef
    RUN /opt/chefdk/bin/chef-client -z --config ${chef_config_path}/client.rb -o "role[${chef_role}]" --environment "${chef_environment}" --log_level info --force-formatter --chef-zero-port 8889

Build Image Locally

  1. Change directories to the root of the cookbook
  2. Build Image
    docker build -f Dockerfile -t <image tag name> .
    1. Example with none Docker Hub username/org tag
      docker build -t cookbook_name:latest .
      Example With multiple tags
      docker build -t supercoder/cookbook_name:2.2.3 -t supercoder/cookbook_name:latest .

Related Articles

Functioning Example