Import Terraform Configuration
Terraform supports bringing your existing infrastructure under its
management. By importing resources into Terraform, you can safely and
consistently manage your infrastruture using a predictable workflow.
When you create new infrastructure with Terraform, you usually use the following workflow:
Write Terraform configuration that defines the infrastructure you want to create.
Review the Terraform plan to ensure the configuration will result in the expected infrastructure.
Apply the configuration to have Terraform create your infrastructure.
Terraform stores information about your infrastructure in a state file. To update your infrastructure, you first modify your configuration, and then use Terraform to plan and apply the required changes. Terraform uses the data in your state file to determine the changes it needs to make to your infrastructure.
You can use the import
command to migrate existing resources into your Terraform state file. The import
command does not currently generate the configuration for the imported resource, so you must write the corresponding configuration block to map the imported resource to it.
Importing infrastructure involves five steps:
- Identify the existing infrastructure you will import.
- Import infrastructure into your Terraform state file.
- Write Terraform configuration that matches that infrastructure.
- Review the Terraform plan to ensure the configuration matches the expected state and infrastructure.
- Apply the configuration to update your Terraform state.
In this tutorial, you will create a Docker container with the Docker CLI. Then, you will import the container into a new Terraform project and begin using the Terraform workflow to modify the container.
Warning
Importing infrastructure manipulates Terraform state and
can corrupt the state file for existing projects. Make a backup
of your terraform.tfstate
file and .terraform
directory before using
Terraform import on a real Terraform project, and store them securely.
Prerequisites
You can complete this tutorial using the same workflow with either Terraform OSS or Terraform Cloud.
Terraform Cloud is a platform that you can use to manage and execute your Terraform projects. It includes features like remote state and execution, structured plan output, workspace resource summaries, and more.
Select the Terraform Cloud tab to complete this tutorial using Terraform Cloud.
This tutorial assumes that you are familiar with the Terraform workflow. If you are new to Terraform, complete the Get Started collection first.
In order to complete this tutorial, you will need the following:
- Docker installed and running.
- Terraform v1.2+ installed locally.
Create a Docker container
Create a container named hashicorp-learn
using the latest NGINX
image from Docker Hub, and publish that container's port 80 (HTTP) to your local
host system's port 8080. You will import this container in this tutorial.
Use docker ps
to verify that the container is running.
Visit the address 0.0.0.0:8080
in your web browser to see the NGINX default
index page.
Now you have a Docker image and container to import into your project and manage with Terraform.
Initialize configuration
Now, clone the example repository for this tutorial.
Change to the repository directory.
This directory organizes Terraform configuration across three files:
terraform.tf
configures the Terraform and provider versionsmain.tf
configures the Docker providerdocker.tf
will contain the configuration for Docker container you import
Initialize this configuration.
Import the container into Terraform
Next, define an empty docker_container
resource in your docker.tf
file,
which represents a Docker container with the Terraform resource ID
docker_container.web
.
Next, run docker ps
to find the name of the container you want to import - in
this case, the container you created in the previous step.
Now run terraform import
to attach the existing Docker container to the
docker_container.web
resource you just created. Terraform import requires this
Terraform resource ID and the full Docker container ID. In the following
example, the command docker inspect --format="{{.ID}}" hashicorp-learn
returns the
full SHA256 container ID.
Note
The ID terraform import
requires varies by resource type. You can find the required ID
in the provider documentation for the resource you wish to import. For this example, consult the Docker provider
documentation.
Review the contents of your state file by running terraform show
.
Importing the container pulled all of the displayed data about the resource
into your state file under the resource ID you specified
(docker_container.web
). However, Terraform import does not create the
configuration for the resource.
Create configuration
In order to continue managing the imported container using Terraform, you must also create corresponding configuraton for it.
Run terraform plan
. Terraform shows errors because your configuration does not have the required image
and name
arguments for the container resource. Terraform cannot generate a plan for a resource
that is missing required arguments.
There are two approaches you can use to update the configuration in docker.tf
to match the
state you imported:
- Accept entire current state as-is. This approach is often faster, but can lead to overly verbose configuration since not all attributes in state are necessary in the configuration.
- Cherry-pick required attributes into configuration one at a time. This creates a more manageable configuration, but requires understanding which attributes are required.
You may find both of these methods useful in different circumstances. Try either or both of these approaches using the tabs below.
To use current state as configuration, you will:
Copy the Terraform state for the imported resource into a configuration file. You will base the configuration for the resource on its definition in state.
Run
terraform plan
to identify and remove read-only configuration arguments.Re-run
terraform plan
to confirm the configuration is correct.Run
terraform apply
to finish synchronizing your configuration, state, and infrastructure.
Use terraform show
to copy your Terraform state into your docker.tf
file.
Warning
The >
symbol replaces the entire contents of docker.tf
with the output of the terraform show
command. If your configuration already manages other
resources, you must edit the output of terraform show
to remove
existing resources whose configuration you do not want to replace, and
merge the new resources into your existing configuration.
Review the contents of docker.tf
.
Now run terraform plan
. Terraform will show warnings and errors about a
deprecated argument (links
), and several read-only arguments (ip_address
,
network_data
, gateway
, ip_prefix_length
, id
).
These read-only arguments are Docker container attributes that Terraform stores
in state but that it cannot set through configuration because Docker manages them internally.
Terraform can set the links
argument with configuration, but still throws a warning because the argument is deprecated and future versions of the Docker provider may not support it.
Remove all six of these attributes from your docker.tf
configuration file
before continuing with the next step.
When importing real infrastructure, consult the provider documentation to learn
what each argument does. This will help you determine how to handle any
errors or warnings from the plan step. For example, the documentation for the
links
argument is in the Docker provider
documentation.
Now verify that you resolved the errors by re-running terraform plan
.
Notice that Terraform plans to destroy then recreate your Docker container
because your configuration does not set the env
attribute..
Add env
to your docker_container.web
resource.
Verify that you resolved the errors by re-running terraform plan
.
The plan should now execute successfully. Notice that the plan indicates that
Terraform will update the container in place to add the attach
, logs
,
must_run
, and start
attributes.
Terraform uses these attributes to create Docker containers, but Docker does not
store them. As a result, terraform import
did not load their values into state.
When you plan and apply your configuration, the Docker provider will assign the
default values for these attributes and save them in state, but they will not
affect the running container.
Note
Provider documentation may not indicate if a change is safe. You must understand the lifecycle of the underlying resource in order to know if a given change is safe to apply.
Apply the changes to finish syncing your Terraform configuration
and state with the Docker container they represent. Remember to confirm the
apply step with a yes
.
Now your configuration file, Terraform state, and the container are all in sync, and you can use Terraform to manage the Terraform container as you normally would. Because this apply step changed the container's state rather than destroying and recreating it, the container ID did not change, and the container continued running during the process.
Since the approach shown here loads all of the attributes represented in Terraform state, your configuration includes optional attributes whose values are the same as their defaults. Which attributes are optional, and their default values, will vary from provider to provider, and can be found in the provider documentation.
Optionally, you can remove all of these attributes, keeping only the required attributes and any that are specific to your container. After removing these unnecessary attributes, your configuration should match the following.
Note
Your image ID may be different from the one shown here.
At this point, running terraform plan
or terraform apply
will show no
changes, and your configuration only includes the minimum set of attributes
needed to recreate the container as-is.
If you want to try the other method for generating configuration, use the following steps to revert the changes you made in the previous section, then switch to the other tab.
Remove everything inside the
"docker_container" "web"
block indocker.tf
, so that the file only containsresource "docker_container" "web" { }
.Remove the container from your Terraform state.
Re-import the container to Terraform state.
Otherwise, proceed with the next step to verify your configuration.
Verify import
Regardless of which method you used, Terraform now manages your Docker container. Use the Docker CLI to inspect the container.
The "Status" of the container did not change, confirming that the import process did not affect the container's operations. The ID has not changed either, confirming that this is the same container you created at the beginning of this tutorial.
Visit 0.0.0.0:8080
in your web browser to verify that the container still
works as intended.
Create image resource
In some cases, you can bring resources under Terraform's control
without using the terraform import
command. This is often the case for
resources that are defined by a single unique ID or tag, such as Docker images.
In your docker.tf
file, the docker_container.web
resource specifies the
SHA256 hash ID of the image used to create the container. This is how Docker
stores the image ID internally, and so terraform import
loaded the image ID
directly into your state. However the image ID is not as human readable as the
image tag or name, and it may not match your intent. For example, you might want
to use the latest version of the "nginx" image.
Retrieve the image's tag name by running the following command. Replace the
image ID with the image ID from docker.tf
.
Then add the following configuration to your docker.tf
file to represent this
image as a resource.
Warning
Do not replace the image
value in the docker_container.web
resource yet, or Terraform will destroy and recreate your container. Since
Terraform did not yet load the docker_image.nginx
resource into state, it
does not have an image ID to compare with the hardcoded one, which will force replacement. To work around this, define and create the image resource first, then update the container to reference it, as shown in this tutorial.
Run terraform apply
to create an image resource in state. Remember to confirm
the apply step with a yes
.
Now that Terraform created a resource for the image, you can reference it in
your container's configuration. Change the image
value for
docker_container.web
to reference the new image resource.
Since docker_image.nginx.latest
will match the hardcoded image ID you
replaced, terraform apply
will show no changes.
Note
If the image ID for the tag nginx:latest
changed between the time
you first created the Docker container and when you run this command, Docker will
destroy the container and then recreate it with the new image.
Manage the container with Terraform
Now that Terraform manages the Docker container, use Terraform to change the its configuration.
In your docker.tf
file, change the container's external port from 8080
to
8081
.
Apply the change. Terraform will destroy and recreate the
container with the new port configuration. Remember to confirm the apply step
with a yes
.
Now verify that Terraform replaced the container with a new one with the new
configuration by running docker ps
or visiting 0.0.0.0:8081
in your web
browser.
Notice that the container ID has changed. Because changing the port configuration required destroying and recreating it, this is a completely new container.
Destroy infrastructure
You have now imported your Docker container and the image used to create it into Terraform.
Destroy the container and image by running terraform destroy
. Respond yes
to the prompt to confirm the operation.
Finally, run docker ps
to validate that the container was destroyed.
If you used Terraform Cloud for this tutorial, after destroying your resources, delete the learn-terraform-import
workspace from your Terraform Cloud organization.
Tip
Since you added both the image and the container to your Terraform configuration, Terraform will remove both from Docker. If there were another container using the same image, the destroy step would fail. Remember that importing a resource into Terraform means that Terraform will manage the entire lifecycle of the resource, including destruction.
Limitations and other considerations
There are several important things to consider when importing resources into Terraform:
Terraform import uses the current state of your infrastructure reported by the Terraform provider. It cannot determine:
- the health of the infrastructure.
- the intent of the infrastructure.
- changes made to the infrastructure that are not in Terraform's control, such as the state of a Docker container's filesystem.
Importing involves manual steps which can be error prone, especially if the operator lacks context about the purpose and history of the infrastructure.
Importing manipulates the Terraform state file. You may want to create a backup before importing new infrastructure.
Terraform import does not detect or generate relationships between infrastructure.
Terraform import does not detect which default attributes you can skip setting.
Not all providers and resources support Terraform import.
Importing a resource into Terraform does not mean that Terraform can destroy and recreate it. For example, the imported infrastructure could rely on other unmanaged infrastructure or configuration.
If you store your state in a remote backend, you may need to set local variables equivalent to the remote workspace variables. The
import
command always runs locally and cannot access data from the remote backend, unlike commands likeapply
, which run inside your Terraform Cloud environment.
Following Infrastructure as Code (IaC) best practices, such as immutable infrastructure, can help prevent many of these problems.
You can use tools such as Terraformer to automate some of the manual steps required to import infrastructure. HashiCorp does not endorse or support these tools, and they are not part of Terraform.
Next step
In this tutorial, you learned how to bring existing infrastructure under Terraform management. You reviewed the different approaches for developing configuration for imported resources and considerations and limitations of the import workflow.
Review the following resources to learn more about how to use Terraform to safely and consistently manage your infrastructure:
Review the Terraform Import documentation.
Learn how to migrate configuration to Terraform Cloud.
Learn how to create reusable configuration with modules.
Learn how to manage a resource in Terraform state.