Catatan perev. : Penulis bahan ini adalah seorang arsitek di Barclays dan penggemar Sumber Terbuka Inggris Ian Miell. Ini bertujuan untuk membuat gambar Docker yang nyaman (dengan biner "tidur"), yang tidak perlu diunduh, tetapi cukup salin melalui salin & tempel. Dengan percobaan, kesalahan, dan eksperimen dengan kode Assembler, ia mencapai tujuan dengan menyiapkan gambar berukuran kurang dari satu kilobyte.
Ini dia (disandikan dalam base64)H4sICIa2A1sCA2IA7Vrrbts2FFYL7M9+7QUGGNyfDYhtkuJFFLAhWZOhBYJmaLMOWBAEFC+xVlkyJLpYEBjdY+0l+k6jfGvqtkEWp2qD8TMg8vAqnsNzDg9lQhhmEjHDhY4zgWJBBUQJ5ZnCGAubMUQMyhJqoRRMJxYbo7Q2CedYxlQO/myqMroeEEHICIngApspxohEKI4h5DHmGEUQQw7jqAejDjBtnKz9q2w7zubi7gkugazVKHdGuWltQArkWDMCdoCqSpufg/QSPK4aV8pxW+nL96uxzMu39G+NqRe5PeekGj13Oi9BamXRmCtl1dS9X2jqel147C7W+aOJKd8dZ04dlcqsSw7KVyA9Ab/uHT/+cTht6mFRKVkMmywv0yv0mnxbMc8sSP8Apzvg0ViDtJwWxQ54Mpbny5W9qIrp2DSrmt+r+mVenu/ny+UelK6+mFR56VYtjsqfp3mxHupQZqZYdp/NGeo850x99r9j7QloyWEz8kvpK//47vuymvzQ29vf79m8MKnIaIa8bUmwRdByw6TKREIoIzE3xBrjrY7MGDUilomQ3GrNrFaIKqSZ4lkvL3tD12sn/IQCrI10xtcC7C1kH9I+xseQpYilRAwoZ5AI9IcfWFfqpRfzK1M3eeUZDRAfQDGAfc/jHTDKG1fVXiInlzcfctnwLPP9Vszs9VXvUzFy5jlZV5WzTbtN3cWkZWkhL/yS2gXm1p7lumkl24wkpv51FbYcU0EZy7SV0ucEZowkiCjvLbAVikCaGUqhyjT0c0Lj/YrElmmSWANOZ7MooHPwRCiLRaJEzBXKFGTCy49lUHNKjEigVdD6H4uTzPj9wzDCSawU0TQT2ujhjVwjgZzSj/n/eX7D/xPm/T8N/v/Ll/+Lg2fPnxw93eL85xFvyB9Rn4TzXwdAAxiMYLD/t9f/7eM/xDja1P+YBf3vKP7L2+PnttsA/IfjcQiE7nkgdH18Ey4O7pjdH7ygmX0p9n8eFA5aG3pb+0/eP/9jzFmw/13AdTBHK3/OPx7/Ic4X8qecQ9K244QG/98JXh8c/vLwwYM1/TD6KWqpv6LdOb37gT67URKterTpVxu1V9PXq3lW1d8skn++9Y83f4cDeEBAQMBnwliWuTWNu8l33G38/3X3fzGk79wFQ4S4Lwr+vwOcXIJHy4ANkLv4L4APcJ6ZSXUsz+efh1xaSOf3VxstHS6+H/nSu4s6wOns9OugxrdG7WXV5K6qc9NEn0n/ESab+s9o0P+O7v9ce1WzVNI7uAiczYI6BgQEBNwD/AvqV/+XACoAAA==
Bagaimana saya sampai pada ini?
Seorang kolega pernah menunjukkan gambar Docker yang ia gunakan untuk menguji kelompok Kubernetes. Dia tidak melakukan apa-apa: dia hanya berlari di bawah dan menunggu kamu untuk membunuhnya.
βLihat, hanya butuh 700 kilobyte! Unduhan sangat cepat! "
Dan kemudian saya menjadi penasaran gambar Docker minimal apa yang bisa saya buat. Saya ingin mendapatkan satu yang dapat dikodekan dalam base64 dan dikirim secara harfiah ke mana saja dengan copy & paste sederhana. Karena gambar Docker hanya file tar dan file tar hanyalah file, semuanya harus berfungsi.
Biner kecil
Pertama-tama, saya membutuhkan biner Linux yang sangat kecil yang tidak melakukan apa-apa. Dibutuhkan sedikit keajaiban - dan di sini ada dua artikel yang indah, informatif, dan dapat dibaca tentang cara membuat executable kecil:
Saya tidak perlu "Hello World", tetapi sebuah program yang hanya tidur dan berjalan di x86_64. Saya mulai dengan contoh dari artikel pertama:
SECTION .data msg: db "Hi World",10 len: equ $-msg SECTION .text global _start _start: mov edx,len mov ecx,msg mov ebx,1 mov eax,4 int 0x80 mov ebx,0 mov eax,1 int 0x80
Jalankan:
nasm -f elf64 hw.asm -o hw.o ld hw.o -o hw strip -s hw
Ternyata biner
504 byte .
Tapi tetap saja, tidak perlu menggunakan "Hello World" ... Pertama, saya menemukan bahwa bagian
.data
atau
.text
tidak diperlukan dan pemuatan data tidak diperlukan. Selain itu, bagian atas dari bagian
_start
berkaitan dengan output teks. Akibatnya, saya mencoba kode berikut:
global _start _start: mov ebx,0 mov eax,1 int 0x80
Dan itu dikompilasi seawal
352 byte .
Tetapi ini bukan hasil yang diinginkan, karena program hanya mengakhiri pekerjaannya, dan kita membutuhkannya untuk tidur. Sebagai hasil dari penelitian tambahan, ternyata perintah
mov eax
mengisi register prosesor dengan nomor panggilan sistem Linux yang sesuai, dan
int 0x80
melakukan panggilan itu sendiri. Ini dijelaskan lebih rinci di
sini .
Dan di
sini saya menemukan daftar yang diinginkan. Syscall 1
exit
, dan yang kita butuhkan adalah
syscall 29:pause
. Program berikut ini ternyata:
global _start _start: mov eax, 29 int 0x80
Kami menyimpan 8 byte lagi: kompilasi menghasilkan
344 byte , dan sekarang ini adalah biner yang cocok untuk kami, yang tidak melakukan apa-apa dan mengharapkan sinyal.
Menggali dalam hexes
Saatnya untuk mendapatkan gergaji dan menangani biner ... Untuk ini, saya menggunakan
hexer , yang pada dasarnya adalah vim untuk file biner dengan kemampuan untuk langsung mengedit hex. Setelah percobaan panjang, saya dapatkan dari ini:

... ini dia:

Kode ini melakukan hal yang sama, tetapi perhatikan berapa banyak garis dan spasi yang tersisa. Dalam proses pekerjaan saya, saya dibimbing oleh
dokumen semacam itu , tetapi pada umumnya itu adalah jalan coba-coba.
Jadi, ukurannya menurun menjadi
136 byte .
Kurang dari 100 byte?
Saya ingin tahu apakah saya bisa melangkah lebih jauh. Setelah membaca
ini , saya berasumsi bahwa mungkin untuk mencapai 45 byte, tetapi sayangnya! - tidak. Trik yang dijelaskan di sana dirancang hanya untuk binari 32-bit, tetapi untuk yang 64-bit, mereka tidak lulus.
Yang terbaik yang saya kelola adalah mengambil
versi program 64-bit ini dan membuatnya menjadi panggilan sistem saya:
BITS 64 org 0x400000 ehdr: ; Elf64_Ehdr db 0x7f, "ELF", 2, 1, 1, 0 ; e_ident times 8 db 0 dw 2 ; e_type dw 0x3e ; e_machine dd 1 ; e_version dq _start ; e_entry dq phdr - $$ ; e_phoff dq 0 ; e_shoff dd 0 ; e_flags dw ehdrsize ; e_ehsize dw phdrsize ; e_phentsize dw 1 ; e_phnum dw 0 ; e_shentsize dw 0 ; e_shnum dw 0 ; e_shstrndx ehdrsize equ $ - ehdr phdr: ; Elf64_Phdr dd 1 ; p_type dd 5 ; p_flags dq 0 ; p_offset dq $$ ; p_vaddr dq $$ ; p_paddr dq filesize ; p_filesz dq filesize ; p_memsz dq 0x1000 ; p_align phdrsize equ $ - phdr _start: mov eax, 29 int 0x80 filesize equ $ - $$
Gambar yang dihasilkan adalah
127 byte . Tentang ini, saya berhenti berusaha mengurangi ukuran, tetapi saya menerima proposal.
Docker Kecil
Sekarang ada biner yang mengimplementasikan menunggu tanpa akhir, ia masih menyimpannya dalam gambar Docker.
Untuk menyimpan setiap byte yang mungkin, saya membuat biner dengan nama file dari satu byte -
t
- dan meletakkannya di
Dockerfile
, membuat gambar yang hampir kosong:
FROM scratch ADD t /t
Perhatikan bahwa tidak ada
CMD
di
Dockerfile
, karena ini akan meningkatkan ukuran gambar. Untuk memulai, Anda harus melewati perintah melalui argumen untuk
docker run
.
Selanjutnya,
docker save
membuat file tar, dan kemudian dikompres dengan kompresi gzip maksimum. Hasilnya adalah file gambar Docker portabel dengan ukuran kurang dari 1000 byte:
$ docker build -tt . $ docker save t | gzip -9 - | wc -c 976
Saya juga mencoba untuk mengurangi ukuran file tar dengan bereksperimen dengan file manifest Docker, tetapi sia-sia: karena spesifik dari format tar dan algoritma kompresi gzip, perubahan tersebut hanya menyebabkan pertumbuhan gzip akhir. Saya mencoba algoritma kompresi lainnya, tetapi gzip ternyata menjadi yang terbaik untuk file kecil ini.
PS dari penerjemah
Baca juga di blog kami: