Atlas Terraform Provider Quickstart
Intro
In this guide we will quickly go through setting up the Atlas Terraform Provider locally and demonstrate some of its basic features.
Installing Terraform
To get started, you will need Terraform installed on your system. For macOS users, you can install it using Homebrew:
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
For other operating systems, follow the instructions on the official Terraform website.
Set up a local database
Next, we will set up a MySQL database that we'll manage using the Atlas Terraform Provider.
This step requires Docker to be installed on your system. If you don't have Docker installed, you can find installation instructions on the Docker website.
Run the following command to start a MySQL container with Docker:
docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=pass -e MYSQL_DATABASE=myapp mysql:8
Verify the MySQL container is ready before proceeding:
docker exec mysql mysql -uroot -ppass -e "SELECT 1"
If the command returns a result, MySQL is ready to use.
Install the Atlas Terraform Provider
Create a file named main.tf
with the following content to configure the Atlas provider:
terraform {
required_providers {
atlas = {
source = "ariga/atlas"
version = "~> 0.9.7"
}
}
}
provider "atlas" {
dev_url = "docker://mysql/8/myapp"
}
The dev_url
configuration uses the docker://
driver to automatically create a temporary container for Atlas's dev-database. This ephemeral container is separate from our manually created MySQL container, which is the actual database we're managing.
Now initialize Terraform to download the provider:
terraform init
This will produce output similar to:
Initializing the backend...
Initializing provider plugins...
- Finding ariga/atlas versions matching "~> 0.9.7"...
- Installing ariga/atlas v0.9.7...
- Installed ariga/atlas v0.9.7 (self-signed, key ID 149262AD73B30060)
...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
...
Define a schema in SQL
We will create a schema.sql
file to define a simple users
table with id
and name
columns.
create table users (
id int not null auto_increment primary key,
name varchar(255) not null
);
Apply a schema
Now we'll create a complete Terraform configuration to apply this schema to our database. Update your main.tf
file
to include:
terraform {
required_providers {
atlas = {
source = "ariga/atlas"
version = "~> 0.9.7"
}
}
}
provider "atlas" {
dev_url = "docker://mysql/8/myapp"
}
data "atlas_schema" "sql" {
src = "file://${path.module}/schema.sql"
}
resource "atlas_schema" "mysql" {
url = "mysql://root:pass@localhost:3306/myapp"
hcl = data.atlas_schema.sql.hcl
}
This configuration includes two important parts:
- The
atlas_schema
data source that loads and normalizes the schema from our SQL file. - The
atlas_schema
resource that applies the schema to our target MySQL database.
To apply the schema, run:
terraform apply
This command will show a plan of what changes will be made to the database:
data.atlas_schema.sql: Reading...
data.atlas_schema.sql: Read complete after 2s [id=p93KLX2q4UI326LN/4cssQ]
Terraform will perform the following actions:
# atlas_schema.mysql will be created
+ resource "atlas_schema" "mysql" {
+ hcl = <<-EOT
table "users" {
schema = schema.myapp
column "id" {
null = false
type = int
auto_increment = true
}
column "name" {
null = false
type = varchar(255)
}
primary_key {
columns = [column.id]
}
}
schema "myapp" {
charset = "utf8mb4"
collate = "utf8mb4_0900_ai_ci"
}
EOT
+ id = (known after apply)
+ url = (sensitive value)
}
Plan: 1 to add, 0 to change, 0 to destroy.
The following SQL statements will be executed:
CREATE TABLE `users` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
Type "yes" when prompted to apply these changes.
To verify that the schema was applied correctly, you can connect to the MySQL database and inspect the tables:
docker exec -it mysql mysql -uroot -ppass myapp -e "DESCRIBE users;"
This command will show the schema of the users
table:
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
+-------+--------------+------+-----+---------+----------------+
Great! You have successfully applied a schema to a MySQL database using the Atlas Terraform Provider.
Evolve the schema
Let's modify our schema to add a new table and a relationship between tables. Update the schema.sql
file
with the following content:
create table `groups` (
id int not null auto_increment primary key,
name varchar(255) not null
);
create table `users` (
id int not null auto_increment primary key,
name varchar(255) not null,
group_id int not null,
foreign key (group_id) references `groups` (id)
);
Now we've added a groups
table and modified the users
table to include a foreign key reference to it.
Apply the updated schema:
terraform apply
The output will show what changes will be made to your database:
data.atlas_schema.sql: Reading...
data.atlas_schema.sql: Read complete after 2s [id=Qhci62i6CFYRQ2CmUOjMeA]
atlas_schema.mysql: Refreshing state... [id=3bc3da59-2110-1460-9495-d886c8d7303b]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
~ update in-place
Terraform will perform the following actions:
# atlas_schema.mysql will be updated in-place
~ resource "atlas_schema" "mysql" {
~ hcl = <<-EOT
+ table "groups" {
+ schema = schema.myapp
+ column "id" {
+ null = false
+ type = int
+ auto_increment = true
+ }
+ column "name" {
+ null = false
+ type = varchar(255)
+ }
+ primary_key {
+ columns = [column.id]
+ }
+ }
table "users" {
schema = schema.myapp
column "id" {
null = false
type = int
auto_increment = true
}
column "name" {
null = false
type = varchar(255)
}
+ column "group_id" {
+ null = false
+ type = int
+ }
primary_key {
columns = [column.id]
}
+ foreign_key "users_ibfk_1" {
+ columns = [column.group_id]
+ ref_columns = [table.groups.column.id]
+ on_update = NO_ACTION
+ on_delete = NO_ACTION
+ }
+ index "group_id" {
+ columns = [column.group_id]
+ }
}
schema "myapp" {
charset = "utf8mb4"
collate = "utf8mb4_0900_ai_ci"
}
EOT
id = "3bc3da59-2110-1460-9495-d886c8d7303b"
# (1 unchanged attribute hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
╷
│ Warning: Atlas Plan
│
│ with atlas_schema.mysql,
│ on main.tf line 18, in resource "atlas_schema" "mysql":
│ 18: resource "atlas_schema" "mysql" {
│
│ The following SQL statements will be executed:
│
│
│ CREATE TABLE `groups` (
│ `id` int NOT NULL AUTO_INCREMENT,
│ `name` varchar(255) NOT NULL,
│ PRIMARY KEY (`id`)
│ ) CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
│ ALTER TABLE `users` ADD COLUMN `group_id` int NOT NULL, ADD INDEX `group_id` (`group_id`), ADD CONSTRAINT `users_ibfk_1` FOREIGN KEY
│ (`group_id`) REFERENCES `groups` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION;
│
╵
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
To verify the schema changes, connect to the MySQL database and inspect the tables again:
docker exec -it mysql mysql -uroot -ppass myapp -e "SHOW TABLES; DESCRIBE users; DESCRIBE \`groups\`;"
You should see both tables with their updated schemas, including the foreign key relationship:
+-----------------+
| Tables_in_myapp |
+-----------------+
| groups |
| users |
+-----------------+
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| group_id | int | NO | MUL | NULL | |
+----------+--------------+------+-----+---------+----------------+
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
+-------+--------------+------+-----+---------+----------------+
Working with an existing database
When working with an existing database that wasn't initially managed by Atlas, you can inspect the current database schema using the Atlas CLI and use it as your baseline. Here's how:
- Inspect the current database schema using the Atlas CLI:
atlas schema inspect -u mysql://root:pass@localhost:3306/your_database > current-schema.my.hcl
This command creates an HCL representation of your database schema in the file current-schema.my.hcl
.
- Use this HCL file in your Terraform configuration:
terraform {
required_providers {
atlas = {
source = "ariga/atlas"
version = "~> 0.9.7"
}
}
}
provider "atlas" {
dev_url = "docker://mysql/8/myapp"
}
data "atlas_schema" "current" {
src = "file://path/to/current-schema.my.hcl"
}
resource "atlas_schema" "mysql" {
url = "mysql://root:pass@localhost:3306/myapp"
hcl = data.atlas_schema.current.hcl
}
- Make modifications to the
current-schema.my.hcl
file to define your desired schema state and apply the changes through Terraform.
Next Steps
Atlas offers two workflows for database schema management:
-
Declarative Workflow - Define the desired schema state and let Atlas handle the migration planning. This is what we used in this guide.
-
Versioned Workflow - Manage schema through sequential migration files with explicit version control. Ideal for production environments with strict change requirements.
For more detailed documentation, visit the provider registry page.