πŸ“šBook Signing at KubeCon EU 2026Meet us at Booking.com HQ (Mon 18:30-21:00) & vCluster booth #521 (Tue 24 Mar, 12:30-1:30pm) β€” free book giveaway!RSVP Booking.com Event
Configuration beginner ⏱ 10 minutes K8s 1.21+

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.

By Luca Berton β€’ β€’ πŸ“– 5 min read

πŸ’‘ Quick Answer: kubectl create configmap myconfig --from-file=config.yaml creates a ConfigMap with the file contents as a data key. Use --from-file=dir/ for entire directories, --from-env-file for 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=v2

Declarative 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=8080

Mount 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.conf

Inject 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_HOST

Architecture

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

IssueCauseFix
Config not updating in podVolume-mounted ConfigMaps auto-update but subPath doesn’tRestart pod or avoid subPath
Binary file corruptedConfigMap is UTF-8 onlyUse binaryData field or a Secret
Key name has dots/slashesFile path used as keyUse --from-file=clean-name=./path/to/file
ConfigMap too large1MB limit per ConfigMapSplit into multiple ConfigMaps
Env vars not refreshingEnv vars only read at container startRestart pod to pick up changes

Best Practices

  1. Use --dry-run=client -o yaml for GitOps β€” kubectl create configmap x --from-file=f --dry-run=client -o yaml > cm.yaml
  2. Avoid subPath for hot-reload β€” subPath mounts don’t receive updates
  3. Use Kustomize configMapGenerator β€” auto-appends hash suffix for rollout on change
  4. Set immutable: true for static configs β€” reduces API server watch load
  5. Split large configs β€” one ConfigMap per concern (app config, nginx config, etc.)

Key Takeaways

  • --from-file creates one key per file (key = filename, value = content)
  • --from-env-file creates 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
#configmap #kubectl #configuration #volumes #environment-variables
Luca Berton
Written by Luca Berton

Principal Solutions Architect specializing in Kubernetes, AI/GPU infrastructure, and cloud-native platforms. Author of Kubernetes Recipes and creator of CopyPasteLearn courses.

Kubernetes Recipes book cover

Want More Kubernetes Recipes?

This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.

Luca Berton Ansible Pilot Ansible by Example Open Empower K8s Recipes Terraform Pilot CopyPasteLearn ProteinLens