How Do I Use Metabase With AWS Fargate?
Introduction
In this guide, we will demonstrate how to deploy Metabase using AWS Fargate with Pulumi. AWS Fargate is a serverless compute engine for containers that works with both Amazon ECS and Amazon EKS. Metabase is an open-source business intelligence tool that allows you to create dashboards and visualizations.
Step-by-Step Explanation
Step 1: Set Up Pulumi Project
- Create a new Pulumi project using TypeScript.
- Configure AWS credentials and region.
Step 2: Create a VPC and Subnets
- Define a new VPC with public and private subnets.
- Create an Internet Gateway and route tables.
Step 3: Set Up ECS Cluster
- Create an ECS cluster.
- Define task execution roles and policies.
Step 4: Define Metabase Task Definition
- Create a task definition for Metabase.
- Specify container image, CPU, memory, and environment variables.
Step 5: Create Fargate Service
- Define a Fargate service for Metabase.
- Configure load balancer and target group.
Step 6: Deploy and Access Metabase
- Deploy the stack using
pulumi up
. - Access Metabase through the load balancer’s DNS name.
Conclusion
By following these steps, you will have a fully functional Metabase deployment running on AWS Fargate. This setup leverages the scalability and manageability of Fargate, allowing you to focus on using Metabase without worrying about the underlying infrastructure.
Full Code Example
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// Create a new VPC
const vpc = new aws.ec2.Vpc("metabase-vpc", {
cidrBlock: "10.0.0.0/16",
enableDnsHostnames: true,
enableDnsSupport: true,
});
// Create public subnet
const publicSubnet = new aws.ec2.Subnet("public-subnet", {
vpcId: vpc.id,
cidrBlock: "10.0.1.0/24",
mapPublicIpOnLaunch: true,
});
// Create private subnet
const privateSubnet = new aws.ec2.Subnet("private-subnet", {
vpcId: vpc.id,
cidrBlock: "10.0.2.0/24",
});
// Create an Internet Gateway
const internetGateway = new aws.ec2.InternetGateway("internet-gateway", {
vpcId: vpc.id,
});
// Create a route table
const routeTable = new aws.ec2.RouteTable("route-table", {
vpcId: vpc.id,
routes: [{
cidrBlock: "0.0.0.0/0",
gatewayId: internetGateway.id,
}],
});
// Associate route table with public subnet
new aws.ec2.RouteTableAssociation("route-table-association", {
subnetId: publicSubnet.id,
routeTableId: routeTable.id,
});
// Create an ECS cluster
const cluster = new aws.ecs.Cluster("metabase-cluster");
// Create IAM role for task execution
const taskExecutionRole = new aws.iam.Role("task-execution-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Action: "sts:AssumeRole",
Principal: {
Service: "ecs-tasks.amazonaws.com",
},
Effect: "Allow",
Sid: "",
}],
}),
});
// Attach policy to the role
new aws.iam.RolePolicyAttachment("task-execution-policy", {
role: taskExecutionRole.name,
policyArn: "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
});
// Define Metabase task definition
const taskDefinition = new aws.ecs.TaskDefinition("metabase-task", {
family: "metabase-task",
cpu: "256",
memory: "512",
networkMode: "awsvpc",
requiresCompatibilities: ["FARGATE"],
executionRoleArn: taskExecutionRole.arn,
containerDefinitions: JSON.stringify([{
name: "metabase",
image: "metabase/metabase:v0.39.4",
portMappings: [{
containerPort: 3000,
hostPort: 3000,
protocol: "tcp",
}],
environment: [{
name: "MB_DB_FILE",
value: "/metabase-data/metabase.db",
}],
}]),
});
// Create a load balancer
const loadBalancer = new aws.lb.LoadBalancer("metabase-lb", {
internal: false,
loadBalancerType: "application",
securityGroups: [],
subnets: [publicSubnet.id],
});
// Create a target group
const targetGroup = new aws.lb.TargetGroup("metabase-tg", {
port: 3000,
protocol: "HTTP",
targetType: "ip",
vpcId: vpc.id,
});
// Create a listener
new aws.lb.Listener("metabase-listener", {
loadBalancerArn: loadBalancer.arn,
port: 80,
defaultActions: [{
type: "forward",
targetGroupArn: targetGroup.arn,
}],
});
// Create a Fargate service
const service = new aws.ecs.Service("metabase-service", {
cluster: cluster.arn,
taskDefinition: taskDefinition.arn,
desiredCount: 1,
launchType: "FARGATE",
networkConfiguration: {
subnets: [publicSubnet.id],
assignPublicIp: true,
},
loadBalancers: [{
targetGroupArn: targetGroup.arn,
containerName: "metabase",
containerPort: 3000,
}],
});
// Export the load balancer DNS name
export const loadBalancerDnsName = loadBalancer.dnsName;
Deploy this code
Want to deploy this code? Sign up for a free Pulumi account to deploy in a few clicks.
Sign upNew to Pulumi?
Want to deploy this code? Sign up with Pulumi to deploy in a few clicks.
Sign upThank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.