Create ConfigMap from File in Kubernetes
Create Kubernetes ConfigMaps from files, directories, and env files with kubectl. Mount as volumes or inject as environment variables in pods.
π‘ Quick Answer:
kubectl create configmap myconfig --from-file=config.yamlcreates a ConfigMap with the file contents as a data key. Use--from-file=dir/for entire directories,--from-env-filefor KEY=VALUE files.
The Problem
You need to inject configuration files into pods but:
- Hardcoding config in container images breaks the build-once-deploy-anywhere principle
- Different environments (dev/staging/prod) need different configs
- Config files can be large (nginx.conf, application.properties) and donβt fit in YAML strings
- Some apps expect files at specific paths
The Solution
Create from a Single File
# File becomes a key in the ConfigMap (key = filename)
kubectl create configmap nginx-config --from-file=nginx.conf
# Custom key name
kubectl create configmap nginx-config --from-file=site.conf=nginx.conf
# Verify
kubectl get configmap nginx-config -o yaml
# data:
# nginx.conf: |
# server {
# listen 80;
# ...
# }Create from a Directory
# Every file in the directory becomes a key
kubectl create configmap app-config --from-file=./config/
# Example directory structure:
# config/
# βββ app.properties
# βββ logging.xml
# βββ routes.json
#
# Result: ConfigMap with 3 keys (app.properties, logging.xml, routes.json)Create from ENV File
# .env format (KEY=VALUE per line)
cat <<EOF > app.env
DATABASE_HOST=postgres.default.svc
DATABASE_PORT=5432
LOG_LEVEL=info
CACHE_TTL=3600
EOF
kubectl create configmap app-env --from-env-file=app.env
# Result:
# data:
# DATABASE_HOST: postgres.default.svc
# DATABASE_PORT: "5432"
# LOG_LEVEL: info
# CACHE_TTL: "3600"Create from Literal Values
kubectl create configmap feature-flags \
--from-literal=ENABLE_DARK_MODE=true \
--from-literal=MAX_UPLOAD_SIZE=10485760 \
--from-literal=API_VERSION=v2Declarative YAML (for GitOps)
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: production
data:
# Inline values
LOG_LEVEL: "info"
WORKERS: "4"
# Multi-line file content
nginx.conf: |
server {
listen 80;
location / {
proxy_pass http://backend:8080;
}
}
application.properties: |
spring.datasource.url=jdbc:postgresql://db:5432/myapp
spring.jpa.hibernate.ddl-auto=validate
server.port=8080Mount as Volume
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: app
image: myapp:1.0.0
volumeMounts:
# Mount entire ConfigMap as directory
- name: config-volume
mountPath: /etc/app/config
# Mount single key as specific file
- name: nginx-volume
mountPath: /etc/nginx/conf.d/site.conf
subPath: site.conf
volumes:
- name: config-volume
configMap:
name: app-config
- name: nginx-volume
configMap:
name: nginx-config
items:
- key: nginx.conf
path: site.confInject as Environment Variables
spec:
containers:
- name: app
# All keys as env vars
envFrom:
- configMapRef:
name: app-env
# Or select specific keys
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_HOSTArchitecture
graph TD
A[Source Files] -->|kubectl create cm --from-file| B[ConfigMap]
A2[.env File] -->|kubectl create cm --from-env-file| B
A3[Literals] -->|kubectl create cm --from-literal| B
B -->|volumeMount| C[Pod Filesystem]
B -->|envFrom| D[Pod Env Vars]
B -->|subPath mount| E[Single File]Common Issues
| Issue | Cause | Fix |
|---|---|---|
| Config not updating in pod | Volume-mounted ConfigMaps auto-update but subPath doesnβt | Restart pod or avoid subPath |
| Binary file corrupted | ConfigMap is UTF-8 only | Use binaryData field or a Secret |
| Key name has dots/slashes | File path used as key | Use --from-file=clean-name=./path/to/file |
| ConfigMap too large | 1MB limit per ConfigMap | Split into multiple ConfigMaps |
| Env vars not refreshing | Env vars only read at container start | Restart pod to pick up changes |
Best Practices
- Use
--dry-run=client -o yamlfor GitOps βkubectl create configmap x --from-file=f --dry-run=client -o yaml > cm.yaml - Avoid subPath for hot-reload β subPath mounts donβt receive updates
- Use Kustomize
configMapGeneratorβ auto-appends hash suffix for rollout on change - Set
immutable: truefor static configs β reduces API server watch load - Split large configs β one ConfigMap per concern (app config, nginx config, etc.)
Key Takeaways
--from-filecreates one key per file (key = filename, value = content)--from-env-filecreates one key per line (KEY=VALUE format)- Volume mounts auto-update (~60s delay), but subPath and env vars donβt
- ConfigMaps are limited to 1MB β use Secrets or external config for larger data
- Always generate declarative YAML for version control:
--dry-run=client -o yaml

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
