tmpfs Mounts
A Docker tmpfs mount is a temporary filesystem backed by memory instead of an image layer, container writable layer, named volume, or host directory. It matters when a container needs fast scratch space or sensitive temporary files that should disappear when the container stops.
Use tmpfs for runtime-only data such as sockets, PID files, short-lived cache files, upload staging areas, and temporary secrets that must not be written into the container layer. Do not use it for anything you expect to survive container removal.
Overview: How tmpfs Mounts Work
A Docker image is a stack of read-only layers. When Docker starts a container, it creates a thin writable container layer on top of those image layers. Normal writes inside the container go to that writable layer, and they can remain with the stopped container until the container is removed.
A tmpfs mount changes that for one path. Before the container process starts, Docker asks the Linux kernel to mount an in-memory temporary filesystem at a target path inside the container’s mount namespace. Files written below that path do not go into the image, the writable container layer, a named volume, or a bind-mounted host directory. They live in memory-backed kernel storage and disappear when the container is stopped.
This is different from a named volume. A volume is Docker-managed persistent storage and is the right default for database files, uploaded content, and durable service state. A tmpfs mount is intentionally temporary. It is also different from a bind mount: a bind mount maps a real host path into the container, while tmpfs creates a fresh temporary filesystem for that container.
tmpfs mounts are a Linux container feature. On Docker Engine for Linux, the memory comes from the Linux host. On Docker Desktop for macOS or Windows, Linux containers run inside Docker Desktop’s Linux VM, so the tmpfs memory is inside that VM. Windows containers do not use Linux tmpfs in the same way.
Because tmpfs uses memory, it is fast but not free. Its contents count toward memory pressure for the container and Docker host or Desktop VM. Docker lets you set a maximum size. If you do not set one, the kernel default may be much larger than the application really needs, so production containers should size temporary mounts deliberately.
tmpfs is especially useful for reducing accidental persistence. For example, an application might write session files to /run or temporary uploads to /tmp/uploads. Mounting those paths as tmpfs makes the lifecycle explicit: the files are runtime state only.
Syntax
Docker supports two command-line forms. The explicit modern form is --mount:
docker run --mount type=tmpfs,target=/path/in/container IMAGE COMMAND
The shorter form is --tmpfs:
docker run --tmpfs /path/in/container[:OPTIONS] IMAGE COMMAND
| Part | Meaning |
|---|---|
type=tmpfs |
Tells Docker to create a memory-backed temporary filesystem. |
target |
The container path where the tmpfs filesystem appears. Some Docker documentation also uses destination. |
tmpfs-size |
Maximum size for the mount when using --mount, such as tmpfs-size=67108864 for 64 MiB. |
tmpfs-mode |
File mode for the mount root when using --mount, such as tmpfs-mode=1777 for a shared temporary directory. |
--tmpfs /path:size=64m,mode=1777 |
Short syntax with comma-separated tmpfs options. |
noexec |
Prevents executing files from the mount when supported by the kernel mount options. |
nosuid |
Ignores set-user-ID and set-group-ID bits on files in the mount. |
nodev |
Prevents device files in the mount from being treated as devices. |
Compose can declare tmpfs mounts on a service:
services:
worker:
image: alpine:3.20
command: sh -c 'echo "ready" > /run/app/status && sleep 300'
tmpfs:
- /run/app:size=16m,mode=1777
Use the modern docker compose command to run Compose projects. The old standalone docker-compose command exists on some machines, but new Docker lessons and projects should use docker compose.
Examples
Example 1: Create temporary runtime files
This container mounts /run/app as tmpfs, writes a status file, lists it, and exits:
docker run --rm --mount type=tmpfs,target=/run/app,tmpfs-size=16777216,tmpfs-mode=1777 alpine:3.20 sh -c 'echo "started" > /run/app/status.txt && ls -l /run/app/status.txt && cat /run/app/status.txt'
Output:
-rw-r--r-- 1 root root 8 Aug 3 12:00 /run/app/status.txt
started
Docker created a 16 MiB in-memory filesystem at /run/app. The file existed only while the container was running. Because --rm removes the container after it exits, there is no stopped container to inspect, but even without --rm, a stopped container would not preserve the tmpfs contents.
Example 2: Prove tmpfs data is not persisted
Start one container that writes to a tmpfs mount, then start a second container with the same target path:
docker run --name tmpfs-first --mount type=tmpfs,target=/scratch,tmpfs-size=8388608 alpine:3.20 sh -c 'echo "temporary" > /scratch/file.txt && cat /scratch/file.txt'
docker rm tmpfs-first
docker run --rm --mount type=tmpfs,target=/scratch,tmpfs-size=8388608 alpine:3.20 sh -c 'test ! -e /scratch/file.txt && echo "scratch is empty"'
Output:
temporary
tmpfs-first
scratch is empty
The name /scratch is only a container path, not a persistent storage identity. The second container gets a new empty tmpfs mount. If this were a named volume, the file could survive and be visible to the replacement container. With tmpfs, that would be a bug because the feature is designed for runtime-only state.
Example 3: Use short --tmpfs syntax with safer mount options
The --tmpfs flag is compact and accepts common Linux tmpfs options:
docker run --rm --tmpfs /tmp/uploads:rw,noexec,nosuid,nodev,size=32m,mode=1777 alpine:3.20 sh -c 'printf "upload chunk\n" > /tmp/uploads/part.txt && df -h /tmp/uploads && cat /tmp/uploads/part.txt'
Output:
Filesystem Size Used Available Use% Mounted on
tmpfs 32.0M 4.0K 32.0M 0% /tmp/uploads
upload chunk
This is a realistic pattern for temporary upload staging. The noexec, nosuid, and nodev options reduce what can be done from the temporary directory. They are not a full security boundary, but they are sensible defaults when the application only needs to read and write data files.
Example 4: Declare tmpfs in Compose
Compose keeps the runtime storage rule beside the service:
services:
api:
image: alpine:3.20
command: sh -c 'mkdir -p /run/app && echo "api-ready" > /run/app/ready.txt && sleep 300'
tmpfs:
- /run/app:size=16m,mode=1777
Run the service and inspect the temporary file:
docker compose up -d
docker compose exec api cat /run/app/ready.txt
docker compose down
Output:
[+] Running 2/2
- Network tmpfs-demo_default Created
- Container tmpfs-demo-api-1 Started
api-ready
[+] Running 2/2
- Container tmpfs-demo-api-1 Removed
- Network tmpfs-demo_default Removed
docker compose down removes the container and network. There is no volume to keep or remove because tmpfs data belongs to the running container lifecycle. This is different from Compose named volumes, which normally survive plain docker compose down.
How It Works Step By Step
- The Docker CLI sends the image name, command, and tmpfs mount specification to the Docker daemon.
- The daemon prepares the container filesystem from the image’s read-only layers plus a new writable container layer.
- Before starting the container’s main process, Docker creates a mount namespace for the container and mounts a Linux
tmpfsfilesystem at the requested target path. - If the image had files at that target path, the mount hides them while the container is running. The image files are not deleted; they are just covered by the mount.
- Reads and writes under the target path go to the in-memory filesystem, not to the container writable layer.
- The kernel enforces the mount size and options such as
noexec,nosuid, andnodevwhere supported. - When the container stops, Docker tears down the mount with the rest of the container runtime resources. The files are gone.
Common Mistakes
Putting durable data on tmpfs
This is wrong for a database because PostgreSQL stores real data at this path:
docker run --name bad-postgres --tmpfs /var/lib/postgresql/data:size=256m -e "POSTGRES_PASSWORD=changeme" postgres:16-alpine
The database may start, but the files are temporary. When the container stops, the database directory disappears. Use a named volume for durable database state:
docker volume create postgres-data
docker run --name good-postgres --mount type=volume,source=postgres-data,target=/var/lib/postgresql/data -e "POSTGRES_PASSWORD=changeme" postgres:16-alpine
Forgetting that tmpfs consumes memory
A large tmpfs mount can create real memory pressure:
docker run --rm --tmpfs /scratch:size=8g alpine:3.20 sh -c 'echo "too much temporary space" > /scratch/note.txt'
This does not immediately allocate 8 GiB, but it allows the mount to grow that large. On a small Docker Desktop VM or production host, that can compete with application memory. Set sizes based on real workload needs, such as size=64m for small runtime files.
Mounting over required image files
If an image contains startup files in /app/tmp and you mount tmpfs there, the running container sees the empty mount instead of the image directory. The fix is to mount a purpose-built path such as /run/app or create required files during startup after the mount exists.
Thinking tmpfs publishes or exposes anything
Storage mounts do not publish network ports. EXPOSE in a Dockerfile is also only metadata and documentation; it does not publish a port to the host. Use docker run -p host_port:container_port or Compose ports when a service must be reachable from the host.
Best Practices
- Use
tmpfsonly for runtime-only data: sockets, PID files, scratch files, short-lived caches, and temporary upload chunks. - Use named volumes for persistent data. Databases, queues, and uploaded user files should not live on
tmpfs. - Set an explicit size with
tmpfs-sizeorsize=instead of relying on a broad kernel default. - Use restrictive options such as
noexec,nosuid, andnodevfor temporary data directories when your application does not need those capabilities. - Mount narrow paths such as
/run/appor/tmp/uploads, not broad system paths. - Remember Docker Desktop stores Linux container memory and tmpfs data inside its Linux VM.
- Do not use
tmpfsas a substitute for secrets management. It can reduce disk persistence, but real secrets should come from your orchestrator’s secret store or mounted secret files. - Pin image tags such as
alpine:3.20andpostgres:16-alpineso examples and deployments are reproducible.
Practice Exercises
- Run an
alpine:3.20container with a 16 MiBtmpfsmounted at/run/demo. Write a file there, print it, then start a new container with the same mount target and confirm the file is gone. - Create a Compose file for a worker service that uses
tmpfsat/tmp/workwithsize=32m. Expected end state: the service can write a temporary file anddocker compose downleaves no volume behind. - Choose storage for three paths:
/var/lib/postgresql/data,/run/app, and./src. Hint: one should be a named volume, one should betmpfs, and one should be a bind mount.
Summary
tmpfsmounts create memory-backed temporary filesystems inside Linux containers.- Writes to a tmpfs mount do not enter the image, container writable layer, named volume, or host bind mount.
- Data on
tmpfsdisappears when the container stops. - Use
tmpfsfor runtime scratch data, not durable application state. - Set explicit sizes and use restrictive mount options for safer temporary directories.
- Mounts can hide image files at the same target path, so choose targets deliberately.
- Use named volumes for persistence, bind mounts for intentional host paths, and
tmpfsfor short-lived in-memory storage.
