tmpfs 마운트

tmpfs 마운트

tmpfs 마운트에 대해 설명드릴게요. 볼륨(Volumes)과 바인드 마운트(bind mounts)는 호스트와 컨테이너 간에 파일을 공유해서 데이터를 영속적으로 보존할 수 있게 해주는데, Linux에서 Docker를 사용한다면 tmpfs 마운트라는 세 번째 옵션도 있어요. tmpfs 마운트는 컨테이너의 쓰기 가능 레이어 밖에 파일을 만들 수 있게 해주지만, 데이터는 호스트 메모리에만 임시로 저장되고 컨테이너가 멈추면 사라져요. 보안이나 성능 보호가 필요할 때, 영속화할 필요 없는 데이터를 다룰 때 유용하답니다.

출처: 공식문서

본문

tmpfs 마운트란?

볼륨과 바인드 마운트는 호스트 머신과 컨테이너 사이에서 파일을 공유할 수 있게 해주는 기능이에요. 이들을 사용하면 컨테이너가 중지된 후에도 데이터를 보존할 수 있죠. 그런데 Linux에서 Docker를 실행 중이라면 tmpfs 마운트라는 또 다른 선택지가 있어요. tmpfs 마운트를 사용하는 컨테이너는 자신의 쓰기 가능 레이어(writable layer) 밖에 파일을 만들 수 있어요.

볼륨이나 바인드 마운트와 달리 tmpfs 마운트는 임시적이에요. 오직 호스트 메모리에만 유지되고, 컨테이너가 멈추면 tmpfs 마운트는 제거되며 거기에 쓴 파일은 영속화되지 않아요.

tmpfs는 메모리에 데이터를 저장하기 때문에, 그 사용량이 컨테이너의 메모리 cgroup 제한(--memory 또는 Compose의 mem_limit)에 포함돼요. tmpfs-size를 크게 설정하거나 호스트에 마운트된 tmpfs를 사용한다고 해서 그 제한 밖의 추가 RAM이 생기는 건 아니에요. 마운트를 가득 채우면 여전히 컨테이너가 OOM(메모리 부족)으로 죽을 수 있죠. 컨테이너의 메모리 메트릭에는 tmpfs 사용량도 포함되니, 런타임 메트릭을 참고하세요.

tmpfs 마운트는 데이터를 호스트 머신이나 컨테이너 어디에도 영속화하고 싶지 않을 때 가장 유용해요. 보안상의 이유일 수도 있고, 애플리케이션이 대량의 비영속 상태 데이터를 써야 할 때 컨테이너 성능을 보호하려는 목적일 수도 있죠.

Important
Docker의 tmpfs 마운트는 Linux 커널의 tmpfs에 직접 매핑돼요. 따라서 임시 데이터가 스왑 파일에 기록되어 파일시스템에 영속화될 수도 있다는 점을 기억하세요.

기존 데이터 위에 마운트하기

컨테이너 안에 이미 파일이나 디렉터리가 있는 경로에 tmpfs 마운트를 만들면, 기존 파일들이 마운트에 의해 가려져요. 비유하자면 Linux 호스트의 /mnt에 파일을 저장해 둔 상태에서 USB 드라이브를 /mnt에 마운트하는 것과 비슷해요. USB 드라이브를 마운트 해제하기 전까지는 /mnt의 기존 내용이 USB 드라이브 내용으로 가려지는 것과 같은 원리죠.

컨테이너에서는 마운트를 제거해서 가려진 파일을 다시 드러내는 간단한 방법이 없어요. 가장 좋은 방법은 마운트 없이 컨테이너를 다시 생성하는 거예요.

tmpfs 마운트의 제한 사항

  • 볼륨이나 바인드 마운트와 달리, tmpfs 마운트는 컨테이너 간에 공유할 수 없어요.
  • 이 기능은 Linux에서 Docker를 실행할 때만 사용할 수 있어요.
  • tmpfs 마운트의 데이터는 컨테이너 메모리 제한에 포함돼요. size= 값을 크게 설정해도 그 제한이 올라가지는 않아요.
  • tmpfs에 권한을 설정하면 컨테이너 재시작 후 권한이 초기화될 수 있어요. 경우에 따라 uid/gid를 설정하는 것이 해결 방법이 될 수 있답니다.

구문(Syntax)

docker run 명령으로 tmpfs를 마운트하려면 --mount 또는 --tmpfs 플래그를 사용할 수 있어요.

$ docker run --mount type=tmpfs,dst=<mount-path>
$ docker run --tmpfs <mount-path>

일반적으로는 --mount를 더 권장해요. 가장 큰 차이는 --mount 플래그가 더 명시적이라는 점이에요. 반면 --tmpfs는 더 간결하고, 마운트 옵션을 더 많이 설정할 수 있어서 유연성이 좋아요.

--tmpfs 플래그는 swarm 서비스에서는 사용할 수 없어요. 그 경우 반드시 --mount를 사용해야 해요.

--tmpfs 옵션

--tmpfs 플래그는 콜론 문자(:)로 구분된 두 개의 필드로 구성돼요.

$ docker run --tmpfs <mount-path>[:opts]

첫 번째 필드는 tmpfs로 마운트할 컨테이너 경로이고, 두 번째 필드는 선택 사항으로 마운트 옵션을 설정할 수 있어요. --tmpfs에서 사용할 수 있는 유효한 마운트 옵션은 다음과 같아요.

옵션 설명
ro 읽기 전용 tmpfs 마운트를 만들어요.
rw 읽기/쓰기 가능한 tmpfs 마운트를 만들어요 (기본 동작).
nosuid 실행 중에 setuidsetgid 비트가 적용되지 않도록 해요.
suid 실행 중에 setuidsetgid 비트가 적용되도록 해요 (기본 동작).
nodev 디바이스 파일을 만들 수는 있지만 동작하지 않아요 (접근 시 오류 발생).
dev 디바이스 파일을 만들 수 있고 완전히 동작해요.
exec 마운트된 파일 시스템에서 실행 가능한 바이너리를 실행할 수 있게 해요.
noexec 마운트된 파일 시스템에서 실행 가능한 바이너리를 실행할 수 없게 해요.
sync 파일 시스템에 대한 모든 I/O가 동기적으로 수행돼요.
async 파일 시스템에 대한 모든 I/O가 비동기적으로 수행돼요 (기본 동작).
dirsync 파일 시스템 내 디렉터리 업데이트가 동기적으로 수행돼요.
atime 파일에 접근할 때마다 파일 접근 시간을 갱신해요.
noatime 파일에 접근해도 파일 접근 시간을 갱신하지 않아요.
diratime 디렉터리에 접근할 때마다 디렉터리 접근 시간을 갱신해요.
nodiratime 디렉터리에 접근해도 디렉터리 접근 시간을 갱신하지 않아요.
size tmpfs 마운트의 크기를 지정해요. 예: size=64m.
mode tmpfs 마운트의 파일 모드(권한)를 지정해요. 예: mode=1777.
uid tmpfs 마운트 소유자의 사용자 ID를 지정해요. 예: uid=1000.
gid tmpfs 마운트 소유자의 그룹 ID를 지정해요. 예: gid=1000.
nr_inodes tmpfs 마운트의 최대 inode 수를 지정해요. 예: nr_inodes=400k.
nr_blocks tmpfs 마운트의 최대 블록 수를 지정해요. 예: nr_blocks=1024.

예시:

$ docker run --tmpfs /data:noexec,size=1024,mode=1777

Linux mount 명령에서 사용할 수 있는 모든 tmpfs 마운트 기능이 --tmpfs 플래그에서 지원되는 건 아니에요. 고급 tmpfs 옵션이나 기능이 필요하다면 특권(privileged) 컨테이너를 사용하거나 Docker 외부에서 마운트를 구성해야 할 수도 있어요.

Caution
--privileged로 컨테이너를 실행하면 상승된 권한이 부여되어 호스트 시스템이 보안 위험에 노출될 수 있어요. 이 옵션은 꼭 필요할 때만, 신뢰할 수 있는 환경에서 사용하세요.

$ docker run --privileged -it debian sh
/# mount -t tmpfs -o <options> tmpfs /data

--mount 옵션

--mount 플래그는 여러 개의 키-값 쌍으로 구성되며, 각 쌍은 쉼표로 구분되고 <key>=<value> 형태를 가져요. 키의 순서는 중요하지 않아요.

$ docker run --mount type=tmpfs,dst=<mount-path>[,<key>=<value>...]

--mount type=tmpfs에서 사용할 수 있는 유효한 옵션은 다음과 같아요.

옵션 설명
destination, dst, target tmpfs로 마운트할 컨테이너 경로.
tmpfs-size tmpfs 마운트의 크기(바이트). 설정하지 않으면 tmpfs 볼륨의 기본 최대 크기는 호스트 전체 RAM의 50%예요.
tmpfs-mode tmpfs의 파일 모드(8진수). 예: 700 또는 0770. 기본값은 1777 또는 world-writable이에요.

예시:

$ docker run --mount type=tmpfs,dst=/app,tmpfs-size=21474836480,tmpfs-mode=1770

컨테이너에서 tmpfs 마운트 사용하기

컨테이너에서 tmpfs 마운트를 사용하려면 --tmpfs 플래그를 쓰거나, --mount 플래그에 type=tmpfsdestination 옵션을 함께 사용하면 돼요. tmpfs 마운트에는 source가 없어요. 다음 예시는 Nginx 컨테이너의 /apptmpfs 마운트를 만드는 모습을 보여줘요. 첫 번째 예시는 --mount 플래그를, 두 번째 예시는 --tmpfs 플래그를 사용했어요.

--mount 플래그 사용

$ docker run -d \
 -it \
 --name tmptest \
 --mount type=tmpfs,destination=/app \
 nginx:latest

docker inspect 출력의 Mounts 섹션을 보면 마운트가 tmpfs인지 확인할 수 있어요.

$ docker inspect tmptest --format '{{ json .Mounts }}'
[{"Type":"tmpfs","Source":"","Destination":"/app","Mode":"","RW":true,"Propagation":""}]

--tmpfs 플래그 사용

$ docker run -d \
 -it \
 --name tmptest \
 --tmpfs /app \
 nginx:latest

마찬가지로 docker inspect 출력의 Mounts 섹션에서 tmpfs 마운트인지 확인해볼 수 있어요.

$ docker inspect tmptest --format '{{ json .Mounts }}'
{"/app":""}

컨테이너를 중지하고 제거하려면 이렇게 해요.

$ docker stop tmptest
$ docker rm tmptest

더 알아보기