debootstrap - Bootstrap a basic Debian system

여기서는 데비안 기반 리눅스 시스템에서 초기 리눅스 파일 시스템을 생성해줄 수 있는 debootstrap이란 프로그램을 간단히 살펴보자.

왜 쓰는가?

아무런 운영체제가 설치되어 있지 않는 PC에 리눅스를 설치하는 것을 생각해 보자. 우분투 ISO를 입힌 USB를 통해 라이브 부팅 후 설치하는데, 이 때 데스크탑에 설치되는 내용은 리눅스 패키지나 설정 등이 복사되겠지만 근본적으로는 리눅스의 일반적인 파일들이다. 즉 /usr, /var, /etc 등의 디렉토리를 만들고 이 곳에 필요한 파일을 복사하는 것이다.

여러 프로그램들은 자신의 설정 등을 정해진 디렉토리로부터 읽어들이거나, 로그 등의 데이터를 정해진 디렉토리에 쓰도록 하여 동작하는데 따라서 이런 디렉토리가 제대로 존재하지 않는 경우 이후 설치될 패키지나 프로그램들이 제대로 동작하지 않게 된다.

ls -la
합계 68
drwxr-xr-x  2 root      root      4096  4월 18 19:28 boot
drwxr-xr-x  4 root      root      4096  6월 12 19:14 dev
drwxr-xr-x 33 root      root      4096  6월 12 19:18 etc
drwxr-xr-x  2 root      root      4096  4월 18 19:28 home
lrwxrwxrwx  1 root      root         7  6월 12 19:14 lib -> usr/lib
drwxr-xr-x  2 root      root      4096  6월 12 19:16 media
drwxr-xr-x  2 root      root      4096  6월 12 19:16 mnt
drwxr-xr-x  2 root      root      4096  6월 12 19:16 opt
drwxr-xr-x  2 root      root      4096  4월 18 19:28 proc
drwx------  2 root      root      4096  6월 12 19:16 root
drwxr-xr-x  4 root      root      4096  6월 12 19:16 run
lrwxrwxrwx  1 root      root         8  6월 12 19:14 sbin -> usr/sbin
drwxr-xr-x  2 root      root      4096  6월 12 19:16 srv
drwxr-xr-x  2 root      root      4096  4월 18 19:28 sys
drwxrwxrwt  2 root      root      4096  6월 12 19:18 tmp
drwxr-xr-x 11 root      root      4096  6월 12 19:16 usr
drwxr-xr-x 11 root      root      4096  6월 12 19:16 var

컨테이너를 생각해 보자. 우분투 이미지 ubuntu:jammy가 있는 경우 이 컨테이너에 docker exec를 사용하여 쉘로 접속해 보면 마찬가지로 리눅스의 기본 파일 시스템 등이 설치되어 있는 것을 확인할 수 있다. 그럼 여기의 루트 파일 시스템은 도대체 어떻게 만들어진 것일까? 라이브 부팅 USB를 통해 컨테이너 이미지를 만든 것도 아닌데 말이다.

images_00001.png

우분투의 클라우드 이미지를 제공하는 cloud-images.ubuntu.com에는 클라우드에서 사용할 공식 우분투 이미지를 다운로드할 수 있는데 여기서 rootfs.tar.gz를 제공하고 이를 풀어서 내용을 보면 바로 위 파일 내용과 같은 것을 알 수 있다. 즉 이 압축파일을 디스크에 풀고 커널과 부트로더를 설치하면 우분투 리눅스로 부팅할 수 있는 것이다.

debootstrap을 사용하면 위 rootfs.tar.gz와 같은 초기 파일 시스템을 동적으로 구성하면서 추가적인 커스텀 패키지를 설치하는 등의 작업을 진행할 수 있다.

간단한 설치와 사용

설치는 다음과 같이 한다.

$ sudo apt-get install debootstrap

실행 파라미터는 다음과 같다.

$ debootstrap [OPTION...]  SUITE TARGET [MIRROR [SCRIPT]]
$ debootstrap [OPTION...]  --second-stage
  • SUITE: 데비안 기반 시스템의 배포판 코드네임(jammy, focal, stretch)
  • TARGET: 루트 파일 시스템을 구성할 디렉토리의 위치. 보통 새로운 디렉토리를 만들고 거기로 이동해서 .로 준다.
  • MIRROR: 미러 주소를 입력한다. SUITE에서 사용하는 코드네임을 통해 자동으로 찾겠지만 더 빠른 저장소를 찾았으면 거기로 바꾸거나 하면 되겠다.

파라미터 간단 설명

rootfs를 구성하는 데 필요한 파라미터는 몇 개 없으므로 간단히 몇 개만 살펴보자.

--arch

debootstrap으로 구성하는 루트 파일 시스템이 돌아갈 아키텍쳐를 설정한다. 예를 들어 데스크탑 amd64에서 라즈베리 파이 arm64에서 사용할 루트 파일 시스템을 만든다고 하면, 당연히 --arch=armhf를 설정한다. 우분투 리눅스를 구성하는 패키지가 해당 아키텍쳐에 맞추어 설치되어야 하므로 당연하다.

--include

패키지를 추가 설치한다. 기본 루트 파일 시스템과 우분투를 구성하는 기본 패키지 이외에도 추가 패키지를 설치할 수 있는데, 이를테면 openssh-server는 필수 구성 요소가 아니기 때문에 새로 설치할 시스템에 ssh 서버가 필수로 설치되어야 한다면 이를 넣어준다. 예를 들어 리눅스 펌웨어 패키지까지 필요하다면 다음과 같이 --include=openssh-server,linux-firmware 두 패키지의 설치를 부트스트랩 과정에 포함할 수 있다.

--exclude

명시된 패키지를 삭제한다. 당연히 잘 알지 못하는 경우에는 무시해도 된다. 자칫하면 부팅이 실패할 것 같다.

--foreign

부트스트랩 과정을 두 단계로 나누어 처리한다. 위에서 --arch를 사용해 현재 호스트의 아키텍쳐와 설치 대상 아키텍쳐가 다르다면 이 --foreign을 사용해서 부트스트랩을 두 단계로 나누어야 한다.

$ dpkg -l | grep dpkg
ii  dpkg              1.21.1ubuntu2.1          amd64        Debian package management system
ii  dpkg-dev          1.21.1ubuntu2.1          all          Debian package development tools
ii  libdpkg-perl      1.21.1ubuntu2.1          all          Dpkg perl modules

데비안 패키지는 단순히 보면 압축 파일 형태이므로 압축을 푸는 것 정도는 아키텍쳐 상관없이 진행할 수 있지만 설치는 pre/post 훅이 현재 아키텍쳐와 맞지 않을 수 있고, 단순히 내 생각이지만 실제로 패키지를 설치하는 패키지인 dpkg가 아키텍쳐 의존적이므로 여기서는 압축만 풀고 뒤에 따라올 --second-stage에서 실제 패키지를 설치하도록 하려는 것이 목적인 것 같다.

사용 예제 #1: 다른 아키텍쳐의 루트 파일 시스템 구성하기

armhf 보드를 가지고 있는데 여기에 새로운 환경의 우분투를 구성하려고 한다. 데스크탑에서 진행한 후 armhf보드의 디스크에 복사하려고 한다.

첫 번째

최신 우분투를 사용하기 위해 SUITEjammy를, TARGET.로, MIRRORkr.ports.ubuntu.com으로 주었다. --variant는 설명으로 보면 다양한 케이스의 루트 파일 시스템을 구성하도록 되어 있는데, 실제로는 minbase한 개만 사용하는 것처럼 나와있고 디폴트도 minbase같아서 없어도 되는 것 같다. --arch=armhf이므로 --foreign을 명시했고, 추가 패키지 openssh-serverlinux-firmware도 함께 설치하기로 했다. 따라서 설치는 두 단계로 진행될거고 여기서는 패키지의 압축을 해제하는 것까지만 진행한다.

sudo debootstrap --variant=minbase --include=openssh-server,linux-firmware --foreign --arch=armhf jammy . http://kr.ports.ubuntu.com/
I: Retrieving InRelease
I: Checking Release signature
I: Valid Release signature (key id F6ECB3762474EDA9D21B7022871920D1991BC93C)
I: Retrieving Packages
I: Validating Packages
I: Resolving dependencies of required packages...
I: Resolving dependencies of base packages...
I: Checking component main on http://kr.ports.ubuntu.com...
I: Retrieving adduser 3.118ubuntu5
I: Validating adduser 3.118ubuntu5
I: Retrieving apt 2.4.5
I: Validating apt 2.4.5
I: Retrieving base-files 12ubuntu4
I: Validating base-files 12ubuntu4
I: Retrieving base-passwd 3.5.52build1
I: Validating base-passwd 3.5.52build1
I: Retrieving bash 5.1-6ubuntu1
I: Validating bash 5.1-6ubuntu1
I: Retrieving bsdutils 1:2.37.2-4ubuntu3
I: Validating bsdutils 1:2.37.2-4ubuntu3
I: Retrieving coreutils 8.32-4.1ubuntu1
I: Validating coreutils 8.32-4.1ubuntu1
I: Retrieving dash 0.5.11+git20210903+057cd650a4ed-3build1
I: Validating dash 0.5.11+git20210903+057cd650a4ed-3build1
...
...
I: Extracting base-files...
I: Extracting base-passwd...
I: Extracting bash...
I: Extracting bsdutils...
I: Extracting coreutils...
I: Extracting dash...
I: Extracting debconf...
I: Extracting debianutils...
I: Extracting diffutils...
I: Extracting dpkg...
...
...

두 번째

패키지에 대한 필요 설정을 진행하거나 설치한다. 루트 파일 시스템을 구성하기 위해 패키지를 설치하거나 하는 작업이 포함되므로 rootfs는 /가 되어야 한다. 따라서 chroot를 통해 해당 위치를 루트로 변경하여야 한다.

$ ls -la
합계 56
drwxrwxr-x 14 root      root      4096  6월 12 20:24 .
drwxrwxr-x 83 root      root      4096  6월 12 20:21 ..
lrwxrwxrwx  1 root      root         7  6월 12 20:24 bin -> usr/bin
drwxr-xr-x  2 root      root      4096  4월 18 19:28 boot
drwxr-xr-x  2 root      root      4096  6월 12 20:24 debootstrap
drwxr-xr-x  4 root      root      4096  6월 12 20:24 dev
drwxr-xr-x 29 root      root      4096  6월 12 20:24 etc
drwxr-xr-x  2 root      root      4096  4월 18 19:28 home
lrwxrwxrwx  1 root      root         7  6월 12 20:24 lib -> usr/lib
drwxr-xr-x  2 root      root      4096  4월 18 19:28 proc
drwx------  2 root      root      4096  4월 18 19:28 root
drwxr-xr-x  2 root      root      4096  4월 18 19:28 run
lrwxrwxrwx  1 root      root         8  6월 12 20:24 sbin -> usr/sbin
drwxr-xr-x  2 root      root      4096  4월 18 19:28 sys
drwxrwxrwt  2 root      root      4096  4월 18 19:28 tmp
drwxr-xr-x 10 root      root      4096  6월 12 20:24 usr
drwxr-xr-x 11 root      root      4096  6월 12 20:24 var

$ ls -la debootstrap 
합계 180
drwxr-xr-x  2 root      root       4096  6월 12 20:24 .
drwxrwxr-x 14 root      root       4096  6월 12 20:24 ..
-rw-r--r--  1 root      root          6  6월 12 20:24 arch
-rw-r--r--  1 root      root        295  6월 12 20:24 base
-rw-r--r--  1 root      root       6525  6월 12 20:24 debian-common
-rwxr-xr-x  1 root      root      24906  6월 12 20:24 debootstrap
-rw-r--r--  1 root      root      26845  6월 12 20:24 debootstrap.log
-rw-r--r--  1 root      root       7750  6월 12 20:24 debpaths
-rw-r--r--  1 root      root      11908  6월 12 20:24 deburis
-rw-r--r--  1 root      root      48413  6월 12 20:24 functions
-rw-r--r--  1 root      root         28  6월 12 20:24 mirror
-rw-r--r--  1 root      root        889  6월 12 20:24 required
-rw-r--r--  1 root      root          6  6월 12 20:24 suite
-rw-r--r--  1 root      root       9969  6월 12 20:24 suite-script
-rw-r--r--  1 root      root          8  6월 12 20:24 variant

debootstrap은 이 --second-stage를 위해 전 단계에서 루트 파일 시스템의 debootstrap/debootstrap 위치에 이런 작업을 처리할 수 있는 바이너리를 함께 배포하므로, 결론은 second-stage에서는 이를 그냥 실행하기만 하면 된다.

$ sudo chroot . debootstrap/debootstrap --second-stage --verbose          
I: Installing core packages...
I: Unpacking required packages...
I: Unpacking base-files...
I: Unpacking base-passwd...
I: Unpacking bash...
I: Unpacking bsdutils...
I: Unpacking coreutils...
I: Unpacking dash...
I: Unpacking debconf...
I: Unpacking debianutils...
I: Unpacking diffutils...
I: Unpacking dpkg... 
I: Unpacking e2fsprogs...
I: Unpacking findutils...
I: Unpacking gcc-12-base:armhf...
I: Unpacking grep... 
I: Unpacking zlib1g:armhf...
...
...
I: Configuring coreutils...
I: Configuring dpkg... 
I: Configuring mount... 
I: Configuring grep...
I: Configuring perl-base...
I: Configuring init-system-helpers...
I: Configuring gzip... 
I: Configuring usrmerge...
I: Configuring procps... 
I: Configuring debconf... 
I: Configuring libpam0g:armhf... 
I: Configuring util-linux... 
I: Configuring dash... 
I: Configuring libpam-modules-bin... 
I: Configuring libssl3:armhf... 
I: Configuring libkrb5-3:armhf... 
I: Configuring libgssapi-krb5-2:armhf... 
I: Configuring libtirpc3:armhf... 
I: Configuring libnsl2:armhf...
I: Configuring libpam-modules:armhf...
I: Configuring passwd...
I: Configuring libpam-runtime...
I: Configuring login...
...
...
I: Configuring libstdc++6:armhf...
I: Configuring libhogweed6:armhf...
I: Configuring libedit2:armhf...
I: Configuring libapt-pkg6.0:armhf...
I: Configuring libp11-kit0:armhf...
I: Configuring openssh-client... 
I: Configuring libgnutls30:armhf...
I: Configuring openssh-sftp-server... 
I: Configuring apt... 
I: Configuring openssh-server...
I: Configuring libc-bin... 
I: Base system installed successfully.

사용 예제: 컨테이너에 기본 리눅스 파일 시스템 구성하기

scratch라는 도커 컨테이너 이미지가 있다. 이 이미지는 이미지 안에 아무런 내용이 없다. 즉 사이즈가 0이다.

This image is most useful in the context of building base images (such as debian and busybox) or super minimal images (that contain only a single binary and whatever it requires, such as hello-world).

따라서 우분투 루트 파일 시스템을 구성한 후 그것을 scratch에 옮긴다면 이게 바로 우분투 컨테이너 이미지가 된다. 다음과 같은 식으로 진행할 수 있을 것이다.

다음과 같은 도커파일로 이 시나리오를 실행해볼 수 있다.

FROM ubuntu:jammy AS builder

WORKDIR /rootfs

RUN apt-get update && \
    apt-get -y install debootstrap

RUN debootstrap jammy .
RUN chroot . \
    apt-get -y autoremove && \
	apt-get -y clean

FROM scratch

COPY --from=builder /rootfs /

CMD ["bash"]

결과는 다음과 같다.

$ docker build -t ubuntubase -f Dockerfile.from-scratch .
Sending build context to Docker daemon  2.048kB
Step 1/8 : FROM ubuntu:jammy AS builder
jammy: Pulling from library/ubuntu
Digest: sha256:b6b83d3c331794420340093eb706a6f152d9c1fa51b262d9bf34594887c2c7ac
Status: Downloaded newer image for ubuntu:jammy
 ---> 27941809078c
Step 2/8 : WORKDIR /rootfs
 ---> Running in 8d272357b7ea
Removing intermediate container 8d272357b7ea
 ---> b3c8fd7ecb57
Step 3/8 : RUN apt-get update &&     apt-get -y install debootstrap
 ---> Running in c26dba043893
Get:1 http://archive.ubuntu.com/ubuntu jammy InRelease [270 kB]
Get:2 http://security.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
Get:3 http://security.ubuntu.com/ubuntu jammy-security/main amd64 Packages [198 kB]
Get:4 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [109 kB]
Get:5 http://security.ubuntu.com/ubuntu jammy-security/universe amd64 Packages [82.3 kB]
Get:6 http://archive.ubuntu.com/ubuntu jammy-backports InRelease [99.8 kB]
Get:7 http://security.ubuntu.com/ubuntu jammy-security/restricted amd64 Packages [188 kB]
Get:8 http://security.ubuntu.com/ubuntu jammy-security/multiverse amd64 Packages [4653 B]
Get:9 http://archive.ubuntu.com/ubuntu jammy/universe amd64 Packages [17.5 MB]
Get:10 http://archive.ubuntu.com/ubuntu jammy/restricted amd64 Packages [164 kB]
Get:11 http://archive.ubuntu.com/ubuntu jammy/main amd64 Packages [1792 kB]
Get:12 http://archive.ubuntu.com/ubuntu jammy/multiverse amd64 Packages [266 kB]
Get:13 http://archive.ubuntu.com/ubuntu jammy-updates/multiverse amd64 Packages [4653 B]
Get:14 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages [348 kB]
Get:15 http://archive.ubuntu.com/ubuntu jammy-updates/universe amd64 Packages [143 kB]
Get:16 http://archive.ubuntu.com/ubuntu jammy-updates/restricted amd64 Packages [209 kB]
Get:17 http://archive.ubuntu.com/ubuntu jammy-backports/universe amd64 Packages [2016 B]
Fetched 21.5 MB in 5s (4101 kB/s)
Reading package lists...
Reading package lists...
Building dependency tree...
Reading state information...
The following additional packages will be installed:
  ca-certificates dirmngr gnupg gnupg-l10n gnupg-utils gpg gpg-agent
  gpg-wks-client gpg-wks-server gpgconf gpgsm libassuan0 libksba8
  libldap-2.5-0 libldap-common libnpth0 libpsl5 libreadline8 libsasl2-2
  libsasl2-modules libsasl2-modules-db libsqlite3-0 openssl pinentry-curses
  publicsuffix readline-common wget
Suggested packages:
  squid-deb-proxy-client debian-archive-keyring arch-test dbus-user-session
  libpam-systemd pinentry-gnome3 tor parcimonie xloadimage scdaemon 
  libsasl2-modules-gssapi-mit | libsasl2-modules-gssapi-heimdal
  libsasl2-modules-ldap libsasl2-modules-otp libsasl2-modules-sql pinentry-doc
  readline-doc
The following NEW packages will be installed:
  ca-certificates debootstrap dirmngr gnupg gnupg-l10n gnupg-utils gpg
  gpg-agent gpg-wks-client gpg-wks-server gpgconf gpgsm libassuan0 libksba8
  libldap-2.5-0 libldap-common libnpth0 libpsl5 libreadline8 libsasl2-2
  libsasl2-modules libsasl2-modules-db libsqlite3-0 openssl pinentry-curses
  publicsuffix readline-common wget
0 upgraded, 28 newly installed, 0 to remove and 5 not upgraded.
Need to get 5418 kB of archives.
After this operation, 13.5 MB of additional disk space will be used.   
Get:1 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 openssl amd64 3.0.2-0ubuntu1.2 [1183 kB]
Get:2 http://archive.ubuntu.com/ubuntu jammy/main amd64 ca-certificates all 20211016 [148 kB]
Get:3 http://archive.ubuntu.com/ubuntu jammy/main amd64 readline-common all 8.1.2-1 [53.5 kB]
Get:4 http://archive.ubuntu.com/ubuntu jammy/main amd64 libreadline8 amd64 8.1.2-1 [153 kB]
Get:5 http://archive.ubuntu.com/ubuntu jammy/main amd64 libsqlite3-0 amd64 3.37.2-2 [643 kB]
Get:6 http://archive.ubuntu.com/ubuntu jammy/main amd64 libpsl5 amd64 0.21.0-1.2build2 [58.4 kB]
Get:7 http://archive.ubuntu.com/ubuntu jammy/main amd64 publicsuffix all 20211207.1025-1 [129 kB]
Get:8 http://archive.ubuntu.com/ubuntu jammy/main amd64 wget amd64 1.21.2-2ubuntu1 [367 kB]
Get:9 http://archive.ubuntu.com/ubuntu jammy/main amd64 libassuan0 amd64 2.5.5-1build1 [38.2 kB]
Get:10 http://archive.ubuntu.com/ubuntu jammy/main amd64 gpgconf amd64 2.2.27-3ubuntu2 [94.1 kB]
Get:11 http://archive.ubuntu.com/ubuntu jammy/main amd64 libksba8 amd64 1.6.0-2build1 [119 kB]
Get:12 http://archive.ubuntu.com/ubuntu jammy/main amd64 libsasl2-modules-db amd64 2.1.27+dfsg2-3ubuntu1 [20.8 kB]
Get:13 http://archive.ubuntu.com/ubuntu jammy/main amd64 libsasl2-2 amd64 2.1.27+dfsg2-3ubuntu1 [53.9 kB] 
Get:14 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libldap-2.5-0 amd64 2.5.11+dfsg-1~exp1ubuntu3.1 [184 kB]
...
...
I: Configuring python3-gi...
I: Configuring python3-netifaces:amd64...
I: Configuring lsb-release...
I: Configuring python3-pkg-resources...
I: Configuring python3-dbus...
I: Configuring python3-apt...
I: Configuring python3-yaml...
I: Configuring netplan.io...
I: Configuring ubuntu-advantage-tools...
I: Configuring networkd-dispatcher...
I: Configuring kbd...
I: Configuring console-setup-linux...
I: Configuring console-setup...
I: Configuring ubuntu-minimal...
I: Configuring libc-bin...
I: Configuring ca-certificates...
I: Base system installed successfully.
Removing intermediate container 1f86f79511a1
 ---> 1654036f8e5d
Step 5/8 : RUN chroot .     apt-get -y autoremove &&    apt-get -y clean
 ---> Running in 57f97aa6b263
Reading package lists...
Building dependency tree...
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Removing intermediate container 57f97aa6b263
 ---> d3c344e366c3
Step 6/8 : FROM scratch
 ---> 
Step 7/8 : COPY --from=builder /rootfs /
 ---> d6699d77a4af
Step 8/8 : CMD ["bash"]
 ---> Running in bc4a6d119844
Removing intermediate container bc4a6d119844
 ---> ca47e40f35b1
Successfully built ca47e40f35b1
Successfully tagged ubuntubase:latest

7단계 스텝에서는 builder에서 구성한 /rootfs를 scratch의 루트로 복사한다. 따라서 ubuntubase:latest는 아래처럼 우분투 22.04가 된다.

$ docker run -t -i ubuntubase:latest /bin/bash
root@bf96e1691e76:/# cat /etc/issue
Ubuntu 22.04 LTS \n \l

root@bf96e1691e76:/# ls -la
total 56
drwxr-xr-x   1 root root 4096 Jun 12 11:38 .
drwxr-xr-x   1 root root 4096 Jun 12 11:38 ..
-rwxr-xr-x   1 root root    0 Jun 12 11:38 .dockerenv
lrwxrwxrwx   1 root root    7 Jun 12 11:37 bin -> usr/bin
drwxr-xr-x   2 root root 4096 Apr 18 10:28 boot
drwxr-xr-x   5 root root  360 Jun 12 11:38 dev
drwxr-xr-x   1 root root 4096 Jun 12 11:38 etc
drwxr-xr-x   2 root root 4096 Apr 18 10:28 home
lrwxrwxrwx   1 root root    7 Jun 12 11:37 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Jun 12 11:37 lib32 -> usr/lib32
lrwxrwxrwx   1 root root    9 Jun 12 11:37 lib64 -> usr/lib64
lrwxrwxrwx   1 root root   10 Jun 12 11:37 libx32 -> usr/libx32
drwxr-xr-x   2 root root 4096 Jun 12 11:37 media
drwxr-xr-x   2 root root 4096 Jun 12 11:37 mnt
drwxr-xr-x   2 root root 4096 Jun 12 11:37 opt
dr-xr-xr-x 411 root root    0 Jun 12 11:38 proc
drwx------   2 root root 4096 Jun 12 11:37 root
drwxr-xr-x   5 root root 4096 Jun 12 11:37 run
lrwxrwxrwx   1 root root    8 Jun 12 11:37 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 Jun 12 11:37 srv
dr-xr-xr-x  13 root root    0 Jun 12 11:38 sys
drwxrwxrwt   2 root root 4096 Jun 12 11:37 tmp
drwxr-xr-x  14 root root 4096 Jun 12 11:37 usr
drwxr-xr-x  11 root root 4096 Jun 12 11:37 var

반면 이렇게 만든 이미지 용량은 매우 크다.(374MB) 별다른 사이즈에 대한 최적화가 전혀 이루어지지 않았기 때문이다. 어플리케이션 실행에 필요한 패키지만을 설치하도록 최적화가 좀 필요하다. debootstrap으로 컨테이너를 구성하길 원하면 --exclude를 사용하여 이미지를 더 줄이거나 하는 식으로 처리할 수 있겠다.

$ docker images ubuntubase       
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
ubuntubase   latest    ca47e40f35b1   10 minutes ago   374MB
$ docker images ubuntu
REPOSITORY   TAG              IMAGE ID       CREATED       SIZE
ubuntu       jammy            27941809078c   5 days ago    77.8MB
ubuntu       jammy-20220531   27941809078c   5 days ago    77.8MB
ubuntu       jammy-20220428   d2e4e1f51132   6 weeks ago   77.8MB