DEV Community

Piotr Hajdas
Piotr Hajdas

Posted on

How to Generate IaC Templates from Your Docker Files

Last year, I found myself in a frustrating cycle. I'd discover a cool open-source project with a Docker configuration but then spend hours creating Infrastructure as Code templates just to deploy it to my favorite cloud provider. Each time, I translated the same Docker setup, i.e., into CloudFormation for AWS, Blueprints for Render, and App Specs for DigitalOcean.

After doing this tedious translation work for the fifth time, I decided there had to be a better way. That's why I built docker-to-iac – to automate the conversion from Docker configurations to deployment-ready IaC templates for various cloud providers in seconds.

Solution: Using docker-to-iac

The docker-to-iac module converts Docker Compose files or Docker run commands into Infrastructure as Code templates for various cloud providers. Here's how to use it:

Setup

First, create a new project and install the necessary dependencies:

mkdir iac-generator cd iac-generator npm init -y npm install @deploystack/docker-to-iac typescript ts-node 
Enter fullscreen mode Exit fullscreen mode

Create a tsconfig.json file:

{ "compilerOptions": { "target": "ES2020", "module": "NodeNext", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true } } 
Enter fullscreen mode Exit fullscreen mode

Basic Implementation

Create a file named generate-template.ts with this code:

import { translate } from '@deploystack/docker-to-iac'; import { writeFileSync, mkdirSync, existsSync } from 'fs'; import { join, dirname } from 'path'; // Docker Compose content - replace with your own or read from a file const dockerComposeContent = ` version: '3' services: web: image: nginx:alpine ports: - "80:80" `; // Generate Render.com Blueprint const result = translate(dockerComposeContent, { source: 'compose', target: 'RND', // RND = Render.com }); // Create output directory const outputDir = 'output'; if (!existsSync(outputDir)) { mkdirSync(outputDir, { recursive: true }); } // Write all generated files Object.entries(result.files).forEach(([path, fileData]) => { const fullPath = join(outputDir, path); const dir = dirname(fullPath); if (!existsSync(dir)) { mkdirSync(dir, { recursive: true }); } writeFileSync(fullPath, fileData.content); console.log(`Created: ${path}`); }); console.log('Done! Check the output directory for your IaC templates.'); 
Enter fullscreen mode Exit fullscreen mode

Run it with:

npx ts-node generate-template.ts 
Enter fullscreen mode Exit fullscreen mode

This will generate a Render.com Blueprint in the output directory.

Practical Example: Web App + Database on Render

Let's create a more realistic example with a web app connecting to a database:

import { translate } from '@deploystack/docker-to-iac'; import { writeFileSync, mkdirSync, existsSync } from 'fs'; import { join, dirname } from 'path'; // Set DB password for variable interpolation const DB_PASSWORD = 'mySecurePassword123'; // Docker Compose for a web app + database const dockerComposeContent = ` version: '3' services: web: image: node:18-alpine command: npm start ports: - "3000:3000" environment: - NODE_ENV=production - DATABASE_URL=postgres://postgres:\${DB_PASSWORD}@db:5432/app db: image: postgres:14 environment: - POSTGRES_PASSWORD=\${DB_PASSWORD} - POSTGRES_DB=app volumes: - pg_data:/var/lib/postgresql/data volumes: pg_data: `; // Generate Render.com Blueprint with service connections const result = translate(dockerComposeContent, { source: 'compose', target: 'RND', // Handle environment variables environmentVariables: { DB_PASSWORD: DB_PASSWORD }, // Configure service connections serviceConnections: { mappings: [ { fromService: 'web', toService: 'db', environmentVariables: ['DATABASE_URL'], property: 'connectionString' } ] } }); // Create output directory and save files const outputDir = 'output-full'; if (!existsSync(outputDir)) { mkdirSync(outputDir, { recursive: true }); } Object.entries(result.files).forEach(([path, fileData]) => { const fullPath = join(outputDir, path); const dir = dirname(fullPath); if (!existsSync(dir)) { mkdirSync(dir, { recursive: true }); } writeFileSync(fullPath, fileData.content); console.log(`Created: ${path}`); }); console.log('Done! Check the output-full directory for your IaC templates.'); 
Enter fullscreen mode Exit fullscreen mode

This code handles:

  • Environment variable substitution
  • Service connections between the web app and database
  • Generating the proper Render.com Blueprint format with correct service types

Deployment

The generated render.yaml will look something like this:

services: - name: web type: web runtime: image image: url: docker.io/library/node:18-alpine startCommand: npm start plan: starter region: oregon envVars: - key: NODE_ENV value: production - key: PORT value: "3000" - key: DATABASE_URL fromDatabase: name: db-db property: connectionString databases: - name: db-db plan: free 
Enter fullscreen mode Exit fullscreen mode

To deploy this Blueprint on Render:

  1. Push the render.yaml file to a GitHub repository
  2. Log in to your Render account
  3. Click "New Blueprint" and select your repository
  4. Review settings and click "Apply Blueprint"

Render will automatically set up both services with the correct configuration and connections between them!

Even Easier: DeployStack.io

Don't want to write any code? DeployStack.io does all this for you:

  1. Submit your GitHub repository with Docker configurations at deploystack.io/submit
  2. DeployStack generates templates for multiple cloud providers
  3. Add generated deployment buttons to your README
  4. Users can deploy your app with a single click

All generated templates are stored in the deploy-templates repository and available under an open-source license.

Conclusion

The docker-to-iac module eliminates hours of manual work translating Docker configurations to IaC templates. Whether you integrate it into your workflow or use DeployStack.io directly, you can provide easy deployment experiences across cloud providers with minimal effort.

Give it a try and let your Docker configurations do the heavy lifting!

Top comments (0)