Follow this guide to package your application as a Helm chart using the docker-compose.yaml
file that you already
have. We will use a simple example containing an application connected to a PostgreSQL database.
volumes:
pg_app_data:
services:
example-app:
image: public.aws.ecr/<repository_id>/example-app:1.0.0
environment:
DB_HOST: database
DB_NAME: app_db
DB_USER: postgres
DB_PASS: postgres
DB_PORT: 5432
APP_PORT: 8000
ports:
- '8000:8000'
depends_on:
- database
database:
image: postgres:14.8-alpine3.18
environment:
POSTGRES_DB: app_db
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
- pg_app_data:/var/lib/postgresql/data
ports:
- '5432:5432'
Create a Helm chart from your Docker Compose
- Create a directory and set up the Helm Chart Directory Structure in it using the
helm create example-app-chart
command.
- Write a deployment object (Kubernetes manifest) for each of the services from the
docker-compose.yaml
file, in the
templates directory. They define the desired state for application pods, ensuring that the specified number of
replicas of the application is running at any given time.
templates/deployments.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres-statefulset
spec:
serviceName: '{{ .Values.db.host }}'
replicas: 1
selector:
matchLabels:
app: postgres-db
template:
metadata:
labels:
app: postgres-db
spec:
containers:
- name: postgres-container
image: postgres:14.8-alpine3.18
env:
- name: POSTGRES_DB
value: '{{ .Values.db.name }}'
- name: POSTGRES_USER
value: '{{ .Values.db.user }}'
- name: POSTGRES_PASSWORD
value: '{{ .Values.db.pass }}'
- name: PGDATA
value: /var/lib/postgresql/data/todo/
ports:
- containerPort: { { .Values.db.port } }
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-app-deployment
spec:
replicas: { { .Values.replicaCount } }
selector:
matchLabels:
app: example-app
template:
metadata:
labels:
app: example-app
spec:
containers:
- name: example-app-container
image: '{{ .Values.example-app.image }}:{{ .Values.example-app.imageVersion }}'
env:
- name: DB_HOST
value: '{{ .Values.db.host }}'
- name: DB_PORT
value: '{{ .Values.db.port }}'
- name: DB_NAME
value: '{{ .Values.db.name }}'
- name: DB_USER
value: '{{ .Values.db.user }}'
- name: DB_PASS
value: '{{ .Values.db.pass }}'
- name: HELM_VERSION
value: '{{ .Chart.Version }}'
- name: APP_PORT
value: '{{ .Values.example-app.service.port }}'
ports:
containerPort: { { .Values.example-app.service.port } }
initContainers:
- name: check-db-ready
image: postgres:14.8-alpine3.18
env:
- name: POSTGRES_HOST
value: '{{ .Values.db.host }}'
- name: POSTGRES_PORT
value: '{{ .Values.db.port }}'
command:
[
'sh',
'-c',
'echo Checking if postgres is up; until pg_isready -h $POSTGRES_HOST -p $POSTGRES_PORT; do echo Waiting
for postgres database to be up...; sleep 2; done; echo Postgres is up!',
]
We can see that example-app service depends on the database service in the docker-compose file. The depends_on field
from Docker Compose, which defines dependencies between services, can be mimicked using initContainers in a Deployment
object. initContainers run to completion before the main application containers start. They can be used to ensure that
a dependent service is ready before starting the main application.
- Write a service object (kubernetes manifest) for each of the services from docker-compose.yaml file, in the templates
directory, to expose the ports your services run on accordingly.
apiVersion: v1
kind: Service
metadata:
name: example-app-service
spec:
type: { { .Values.example-app.service.type } }
selector:
app: example-app
ports:
- protocol: TCP
port: { { .Values.example-app.service.port } }
targetPort: { { .Values.example-app.service.targetPort } }
---
apiVersion: v1
kind: Service
metadata:
name: postgres-service
spec:
selector:
app: postgres-db
ports:
- protocol: TCP
port: 5432
- Create values.yaml file with appropriate values required by your helm chart
replicaCount: 1
example-app:
service:
type: NodePort
port: 8000
targetPort: 8000
image: public.ecr.aws/<repository_id>/example-app
imageVersion: 1.0.0
db:
host: postgres-service
port: 5432
name: app_db
user: postgres
pass: postgres
- Now that you’ve created a helm chart using your Docker Compose follow this guide to publish your helm chart and get
it deployed in a Localops application environment.
Next Steps