Want to play with Terraform on macOS ?
https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli
#https://developer.hashicorp.com/terraform/downloads
brew outdated; brew upgrade
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
==> Fetching hashicorp/tap/terraform
==> Downloading https://releases.hashicorp.com/terraform/1.4.0/terraform_1.4.0_darwin_amd64.zip
######################################################################## 100.0%
...
🍺 /usr/local/Cellar/terraform/1.4.0: 3 files, 68.3MB, built in 4 seconds
# verify by calling help
chrisp:~ sandorm$ <strong> terraform --help plan</strong>
Usage: terraform plan [options] [DIR]
Generates an execution plan for Terraform.
This execution plan can be reviewed prior to running apply to get a
sense for what Terraform will do. Optionally, the plan can be saved to
a Terraform plan file, and apply can take this plan file to execute
this plan exactly.
...
# follow the example
chrisp:learn-terraform-docker sandorm$ nvim main.tf
chrisp:learn-terraform-docker sandorm$ terraform init
Initializing the backend...
Initializing provider plugins...
- Checking for available provider plugins...
The version constraint is derived from the "version" argument within the
provider "docker" block in configuration. Child modules may also apply
provider version constraints. To view the provider versions requested by each
module in the current configuration, run "terraform providers".
# Fix the version
chrisp:learn-terraform-docker sandorm$ cat main.tf
# Set the required provider and versions
terraform {
required_providers {
# We recommend pinning to the specific version of the Docker Provider you're using
# since new versions are released frequently
docker = {
source = "kreuzwerker/docker"
version = "2.7.2"
}
}
}
# Configure the docker provider
provider "docker" {
}
# Create a docker image resource
# -> docker pull nginx:latest
resource "docker_image" "nginx" {
name = "nginx:latest"
keep_locally = true
}
# Create a docker container resource
# -> same as 'docker run --name nginx -p8080:80 -d nginx:latest'
resource "docker_container" "nginx" {
name = "nginx"
image = docker_image.nginx.latest
ports {
external = 8080
internal = 80
}
}
# Or create a service resource
# -> same as 'docker service create -d -p 8081:80 --name nginx-service --replicas 2 nginx:latest'
resource "docker_service" "nginx_service" {
name = "nginx-service"
task_spec {
container_spec {
image = docker_image.nginx.repo_digest
}
}
mode {
replicated {
replicas = 2
}
}
endpoint_spec {
ports {
published_port = 8081
target_port = 80
}
}
}
chrisp:learn-terraform-docker sandorm$ cat main.tf
# Set the required provider and versions
terraform {
required_providers {
# We recommend pinning to the specific version of the Docker Provider you're using
# since new versions are released frequently
docker = {
source = "kreuzwerker/docker"
<strong> version = "2.7.2"</strong>
}
}
}
# Configure the docker provider
provider "docker" {
}
# Create a docker image resource
# -> docker pull nginx:latest
resource "docker_image" "nginx" {
name = "nginx:latest"
keep_locally = true
}
# Create a docker container resource
# -> same as 'docker run --name nginx -p8080:80 -d nginx:latest'
resource "docker_container" "nginx" {
name = "nginx"
image = docker_image.nginx.latest
ports {
external = 8080
internal = 80
}
}
# Or create a service resource
# -> same as 'docker service create -d -p 8081:80 --name nginx-service --replicas 2 nginx:latest'
resource "docker_service" "nginx_service" {
name = "nginx-service"
task_spec {
container_spec {
image = docker_image.nginx.repo_digest
}
}
mode {
replicated {
replicas = 2
}
}
endpoint_spec {
ports {
published_port = 8081
target_port = 80
}
}
}
Code-Sprache: PHP (php)

Plugins are called providers and are downloaded to .terraform directory:
find .terraform
.terraform
.terraform/plugins
.terraform/plugins/darwin_amd64
.terraform/plugins/darwin_amd64/lock.json
.terraform/plugins/darwin_amd64/terraform-provider-docker_v2.7.2_x4
Running terraform plan reveals, image_id is missing.
on main.tf line 42, in resource "docker_service" "nginx_service":
42: image = docker_image.nginx.repo_digest
This object has no argument, nested block, or exported attribute named
"repo_digest".
# version out of date ?
terraform init -v
Terraform v0.12.23
+ provider.docker v2.7.2
Your version of Terraform is out of date! The latest version
is 1.4.0. You can update by downloading from https://www.terraform.io/downloads.html
# download and unzip, mv to /usr/local/bin
erraform -v
Terraform v1.4.0
on darwin_amd64
Code-Sprache: PHP (php)
After updating terraform to 1.4.0 from the website, the docker provider is upgraded to 2.25
terraform init
Initializing the backend...
Initializing provider plugins...
- Finding kreuzwerker/docker versions matching "~> 2.7"...
- Installing kreuzwerker/docker v2.25.0...
<strong>- Installed kreuzwerker/docker v2.25.0 (self-signed, key ID BD080C4571C6104C)</strong>
...
Terraform has created <strong>a lock file .terraform.lock.hcl</strong> to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!Code-Sprache: PHP (php)
Create a plan, save it, apply it
chrisp:learn-terraform-docker sandorm$ t<strong>erraform apply tfplan</strong>
docker_image.nginx: Creating...
docker_image.nginx: Creation complete after 6s [id=sha256:904b8cb13b932e23230836850610fa45dce9eb0650d5618c2b1487c2a4f577b8nginx:latest]
docker_container.nginx: Creating...
docker_service.nginx_service: Creating...
docker_container.nginx: Creation complete after 2s [id=ae0ebb5282aaab9a50bef7071a7c45ad118ad3aedf31eb23615d07e0f167b2e0]
╷
│ Warning: Deprecated attribute
│
│ on main.tf line 28, in resource "docker_container" "nginx":
│ 28: image = docker_image.nginx.latest
│
│ The attribute "latest" is deprecated. Refer to the provider documentation for details.
│
│ (and 3 more similar warnings elsewhere)
╵
╷
│ Error: Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again.
│
│ with docker_service.nginx_service,
│ on main.tf line 38, in resource "docker_service" "nginx_service":
│ 38: resource "docker_service" "nginx_service" {
│
╵
chrisp:learn-terraform-docker sandorm$ docker swarm init
Swarm initialized: current node (yp8uc672ykoik1x5l8htekpza) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-33jsro1sk7hlos5axafiotwlcevhxlww4wj0cjdfr0mglpqozg-clf1a44u9zgazkuogvo4oejyl 192.168.65.3:2377
chrisp:learn-terraform-docker sandorm$ terraform apply tfplan
docker_service.nginx_service: Creating...
docker_service.nginx_service: Creation complete after 2s [id=sjb5lbgpm80pc964qssh95a89]
╷
│ Warning: Deprecated attribute
│
│ on main.tf line 43, in resource "docker_service" "nginx_service":
│ 43: image = docker_image.nginx.latest
│
│ The attribute "latest" is deprecated. Refer to the provider documentation for details.
│
│ (and one more similar warning elsewhere)
╵
<strong>Apply complete! Resources: 1 added, 0 changed, 0 destroyed.</strong>
Code-Sprache: HTML, XML (xml)
We can see docker container, running nginx:
chrisp:learn-terraform-docker sandorm$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f07860272b13 904b8cb13b93 "/docker-entrypoint.…" 35 seconds ago Up 34 seconds 80/tcp nginx-service.2.fr81wrfyppi3y8fnplllpw70l
20a3fba35cf0 904b8cb13b93 "/docker-entrypoint.…" 35 seconds ago Up 34 seconds 80/tcp nginx-service.1.vqui16lbpnpx7rydj4by4kmav
ae0ebb5282aa 904b8cb13b93 "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:8080->80/tcp nginxCode-Sprache: JavaScript (javascript)
