# terraform-provider-docker manages Docker through Terraform, not just images

> The kreuzwerker Terraform provider covers far more than containers and images, spanning Compose stacks, Buildx builders, Swarm services, secrets and plugins plus a set of operational actions, and its cost of adoption is a versioned provider pinned in every configuration.

**kreuzwerker/terraform-provider-docker** — Terraform Docker provider

- Repository: https://github.com/kreuzwerker/terraform-provider-docker
- Stars: 824 · Forks: 216
- Language: Go
- License: MPL-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/kreuzwerker-terraform-provider-docker

## The resource list goes well past containers

The README is explicit that the provider covers more than basic Docker images and containers, and the list it gives is the honest measure of scope. You can manage Compose applications with docker_compose, image builds and registry workflows with docker_image, docker_registry_image and docker_tag, Buildx builders for multi-platform builds with docker_buildx_builder, and Swarm services with docker_service. At runtime there are docker_container, docker_network and docker_volume. Supporting platform objects cover docker_config, docker_secret and docker_plugin. And then there is a set of operational actions: docker_exec, docker_image_import, docker_image_load, docker_image_save, docker_container_export and docker_system_prune. The data sources cover images, image tags and manifests, containers, networks, plugins and container logs. The audience is a team that wants Docker objects to be first class members of a Terraform plan, including the ability to import an image or prune the system as steps in the same graph.

## The example shows a resource and a service side by side

The README example configures the provider, pins a version, and then creates a container, with a Swarm service as the alternative.

```hcl
# 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"
      # or if you want to pull from opentfu
      source = "registry.opentofu.org/kreuzwerker/docker"
      version = "4.6.0"
    }
  }
}
```

The resource block is written so you can read the Docker command it corresponds to.

```hcl
# Create a docker image resource
# -> docker pull nginx:latest
resource "docker_image" "nginx" {
  name         = "nginx:latest"
  keep_locally = true
}
```

The container block that follows draws the parallel with docker run, and the service block with docker service create, including a replicated mode with a replica count and an endpoint spec with a published port and a target port. The comments are doing real work here, because they are the only place the mapping between the declarative resource and the imperative Docker command is spelled out, and that is the thing you will want when reading a plan diff.

## Pinning is the instruction the provider itself gives

The comment inside the required_providers block is worth taking literally. It recommends pinning to the specific version of the provider you are using, because new versions are released frequently. The example pins 4.6.0, and the source can be the official registry or registry.opentofu.org, so the same configuration works whether your team runs Terraform or OpenTofu. That combination of frequent releases and a pin recommendation tells you something about the upgrade cadence: this is a provider that moves, and a configuration that does not pin will be dragged forward by whatever the lock file resolves to. The README also states a floor, that you need at least Terraform 1.1.5 to use the provider. For a team that has been on an earlier major line of the provider itself, the README points at two migration guides in the docs directory, one for moving from v3.x to v4.x and one for v2.x to v3.x, which is the signal that major upgrades here are not cosmetic.

## Building the plugin needs Go and a make target

The provider is a Go plugin and the build instructions are short.

```sh
$ git clone git@github.com:kreuzwerker/terraform-provider-docker
$ make build
```

The README lists Go 1.18.x as the requirement for building the provider plugin, while the go.mod in the repository declares a newer language version, 1.25.8, and the repository carries a .go-version file, so the documented toolchain and the module toolchain have drifted apart and the go.mod is the more reliable guide. The build is driven by a GNUmakefile rather than a plain Makefile, and the release path uses goreleaser with two configurations, a .goreleaser.yml and a .goreleaser-fast.yml, plus a .chglog directory and a cliff.toml for the changelog. The .terraform-registry directory is what lets the provider publish its own documentation to the Terraform Registry, which is where the README says the full resource and data source list lives. The example directories in the repository mirror that structure, with separate folders for resources, data sources, actions, the provider itself, and an ssh-protocol example.

## Actions are the part that behaves unlike a resource

Terraform's model is that a resource has a desired state and the provider converges reality towards it. The action resources do not fit that shape, and they are the part of this provider to understand before relying on it. docker_exec runs a command in a container, docker_image_import and docker_image_load bring images in, docker_image_save and docker_container_export take them out, and docker_system_prune removes unused objects. Each of these is a side effect rather than a piece of state, which means the usual Terraform affordances, a diff before apply, a plan that shows what will change, do not apply to them in the same way. The Compose resource is the interesting third case, since docker_compose manages an application described by a compose file, and a compose file is itself declarative, so the provider is effectively wrapping one declarative format inside another. That works, and it also means a compose stack and the equivalent set of individual container resources are two different ways of saying the same thing, and mixing them in one configuration is a good way to end up with two sources of truth.

## Where a Terraform Docker provider is the wrong shape

The main limit is the operating model, not the feature list. A Terraform provider asserts that a container exists with a given configuration, and a plan against a running container will try to change it. A platform that deploys and then leaves the container alone, whether that is a scheduler or a CI pipeline, has a different contract, and for a workload whose lifecycle is owned elsewhere, putting it in Terraform means the two systems will disagree. The second limit is that the provider drives a Docker daemon over its API, so it manages one host, and the Swarm and Buildx resources point at a different scope, multi-node and multi-platform, but the ordinary container resource is local. The third is the release cadence the README itself flags, combined with a migration guide for each major line, which is real upgrade work rather than a version bump. And the licensing has a wrinkle worth checking before you build on it: the repository is listed under MPL-2.0 while the README badge shows MIT, and the LICENSE file at the root is the one that governs, so read that file rather than either label.

## Conclusion

terraform-provider-docker suits a team that already runs Terraform and wants containers, networks and volumes to be part of the same plan and apply cycle as the rest of the infrastructure, and it suits anyone who wants Compose stacks modelled as resources rather than as an opaque file. It is the wrong choice if you would rather let an orchestrator own the container lifecycle, since a provider that declares containers as desired state is a different operating model from one that deploys and leaves them alone, and it is the wrong choice if you cannot pin provider versions, because the README notes that new versions are released frequently. Before adopting it, read the V3 to V4 migration guide if you are moving from an older line, pin the provider version in required_providers as the example does, and check that your Terraform is at least 1.1.5. The last push was on 2026-10-16 and the current release is v4.6.0 from 2026-09-01.

## FAQ

### What resources does the Docker Terraform provider manage?

Compose applications with docker_compose, images and registry workflows with docker_image, docker_registry_image and docker_tag, Buildx builders with docker_buildx_builder, Swarm services with docker_service, runtime objects with docker_container, docker_network and docker_volume, and platform objects with docker_config, docker_secret and docker_plugin. Actions cover exec, image import and load, image save, container export and system prune.

### How do I install and pin the Docker Terraform provider?

Add it to required_providers with source kreuzwerker/docker, or registry.opentofu.org/kreuzwerker/docker, and set a version such as 4.6.0. The README recommends pinning the specific version because new versions are released frequently, and you need at least Terraform 1.1.5.

### How do I build the Docker Terraform provider from source?

Clone the repository and run make build. The provider plugin is written in Go, the repository includes a GNUmakefile, and the release artifacts are produced with goreleaser.

### What do the Docker provider actions do?

The action resources perform side effects rather than declaring state: docker_exec runs a command in a container, docker_image_import and docker_image_load bring images in, docker_image_save and docker_container_export take them out, and docker_system_prune removes unused Docker objects.

## Sources

- [Issues](https://github.com/kreuzwerker/terraform-provider-docker/issues)
- [kreuzwerker/terraform-provider-docker on GitHub](https://github.com/kreuzwerker/terraform-provider-docker)
- [License: MPL-2.0](https://github.com/kreuzwerker/terraform-provider-docker/blob/master/LICENSE)
- [README](https://github.com/kreuzwerker/terraform-provider-docker/blob/master/README.md)
- [Releases](https://github.com/kreuzwerker/terraform-provider-docker/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/kreuzwerker-terraform-provider-docker
