JavaScript port of Podlet Generate Podman Quadlet files from Docker run commands and compose files. This port was created with the help of Claude Code. I'm cleaning up this code but any suggestions of fixes are welcome.
Complete Docker Compose YAML parsing with multi-service support and systemd integration.
- Container class: Full configuration object matching Rust original
- Quadlet generator: Converts Container objects to Quadlet INI format
- Docker run parser: Full command line parsing with 40+ flags supported
- Compose parser: Complete YAML parsing with multi-service support
- Service dependencies: Automatic systemd unit dependencies from depends_on
- Complex argument handling: Quoted strings, escaping, multi-value flags
- Network & volume handling: Full compose networking and storage support
- Healthchecks: Complete healthcheck configuration support
- Type system: All core data structures (Volume, PortMapping, Environment, etc.)
- Main interface: PodletJS class with complete API
- Validation: Container validation and error handling
npm install podletjs
# Clone the repository
git clone https://github.com/karoltheguy/podletjs.git
cd podletjs
# Install dependencies
npm install
import { PodletJS } from 'podletjs';
const podlet = new PodletJS();
// Parse docker-compose files
const composeYaml = `
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
environment:
NODE_ENV: production
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_DB: myapp
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
`;
const composeQuadlets = podlet.composeToQuadlet(composeYaml, {
unit: {
description: 'My Application Stack',
after: ['network-online.target'],
wants: ['network-online.target']
},
service: { restart: 'always' },
install: { wantedBy: ['multi-user.target'] }
});
console.log('Web service filename:', composeQuadlets[0].filename);
console.log('Web service:', composeQuadlets[0].content);
console.log('DB service filename:', composeQuadlets[1].filename);
console.log('DB service:', composeQuadlets[1].content);
Outputs:
1st Quadlet (web.container
)
# Web service with dependency on db
[Unit]
Description=My Application Stack
Wants=network-online.target db.service
After=network-online.target db.service
[Container]
Image=nginx:alpine
ContainerName=web
PublishPort=8080:80
Environment=NODE_ENV=production
[Service]
Restart=always
[Install]
WantedBy=multi-user.target
2nd Quadlet (db.container
)
[Unit]
Description=My Application Stack
Wants=network-online.target
After=network-online.target
[Container]
Image=postgres:15
ContainerName=db
Volume=db_data:/var/lib/postgresql/data
Environment=POSTGRES_DB=myapp
[Service]
Restart=always
[Install]
WantedBy=multi-user.target
// Parse Docker run commands
const dockerRunCommand = `docker run -d --name web-server -p 8080:80 -e NODE_ENV=production -v data:/app/data nginx:alpine`;
const runQuadlet = podlet.dockerRunToQuadlet(dockerRunCommand, {
unit: { description: 'Web Server Container' },
service: { restart: 'always' },
install: { wantedBy: ['multi-user.target'] }
});
console.log('Docker run Quadlet:', runQuadlet);
Outputs:
[Unit]
Description=Web Server Container
[Container]
Image=nginx:alpine
ContainerName=web-server
PublishPort=8080:80
Volume=data:/app/data
Environment=NODE_ENV=production
[Service]
Restart=always
[Install]
WantedBy=multi-user.target
- Basic:
--name
,--image
, commands and arguments - Networking:
-p/--publish
,--network
,-h/--hostname
- Storage:
-v/--volume
,--tmpfs
,--mount
- Environment:
-e/--env
,--env-file
,--env-host
- Security:
--user
,--cap-add
,--cap-drop
,--security-opt
,--read-only
- Resources:
--memory
,--cpus
,--pids-limit
- Runtime:
--entrypoint
,--workdir
,--init
,--stop-signal
,--stop-timeout
- Health:
--health-cmd
,--health-interval
,--health-timeout
,--health-retries
- Labels:
-l/--label
,--annotation
- Devices:
--device
- DNS:
--dns
,--dns-option
,--dns-search
- Logging:
--log-driver
,--log-opt
- And many more...
- Services:
image
,build
,command
,entrypoint
- Networking:
ports
,networks
,hostname
,dns
- Storage:
volumes
(bind, named, tmpfs),working_dir
- Environment:
environment
,env_file
- Security:
user
,cap_add
,cap_drop
,security_opt
,read_only
- Health:
healthcheck
(test, interval, timeout, retries, start_period) - Dependencies:
depends_on
(converted to systemd unit dependencies) - Runtime:
restart
,tty
,stdin_open
,privileged
,init
- Resources:
mem_limit
,cpus
- Labels:
labels
,container_name
- And more...
# Install dependencies
npm install
# Run all tests (unit + e2e)
npm run test:all
# Run only unit tests
npm run test:unit
# Run only end-to-end tests
npm run test:e2e
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverage
- Pod generation:
--pod
flag support for compose files - Build contexts: Full
build
section handling - Advanced networking: Custom network drivers
- Secrets/Configs: When Quadlet supports them
- Version compatibility: Podman version-specific features
- Some advanced docker run flags added to PodmanArgs only
- Build contexts generate placeholder images
- Advanced compose features like secrets/configs not supported (by design)
src/
├── index.js # Main PodletJS class
├── container.js # Container configuration class
├── quadlet-generator.js # Quadlet file generation
├── compose-parser.js # Docker compose file parser
└── types.js # Core data structures and enums
test/
├── setup.js # Test setup configuration
├── unit/ # Unit tests
│ ├── compose-parser.test.js
│ ├── container.test.js
│ ├── index.test.js
│ └── quadlet-generator.test.js
└── e2e/ # End-to-end tests
├── container.e2e.test.js
├── podlet-js.e2e.test.js
└── quadlet-generator.e2e.test.js
minimist
: Command line argument parsingcomposerize
: Convert Docker run commands to docker-compose format
jest
: Testing framework@jest/globals
: Jest testing utilitiesbabel-jest
: Babel integration for Jest@babel/core
&@babel/preset-env
: ES6+ transpilationfs-extra
: Enhanced file system operations for testingtmp
: Temporary file and directory creation for tests
MPL-2.0 (same as original Podlet)