3 hari sebelum tahun baru ada tugas untuk mentransfer perangkat lunak kami ke klien melalui manajer, pada flash drive. Perangkat lunak adalah platform microservice dengan lusinan gambar buruh pelabuhan dengan banyak pengaturan dan bagan helm sepanjang satu kilometer. Apa yang kami miliki:
- Manajer di Moskow (Saya bukan dari sana)
- Windows
- Tidak ada interaksi langsung (dan jika ada, itu tidak benar-benar membantu)
- buruh pelabuhan no
Pff, pikirku! Saya akan mengambil Golang, menulis program, kompilasi untuk Windows.
... dan 5 jam kemudian saya menyadari ketergesaan kesimpulan saya. Pada saat itu, tawa Nelson teringat untuk pertama kalinya. HA HA Yang menghantui saya sepanjang waktu yang saya habiskan untuk mempelajari masalah ini.
Sebagian besar contoh yang saya temukan memerlukan dockerd. Dua skrip yang tidak menggunakan dockerd, yang ditemukan setelah satu jam googling, satu dan dua . Opsi pertama membantu saya memahami proses mendapatkan semua layer gambar dan file konfigurasi, tetapi tidak mungkin untuk menggunakannya dengan Windows. Dan opsi kedua menunjukkan bahwa bukan hanya berbagai hash yang berkedip di layar, khususnya FIXME ini. Seseorang bisa, tentu saja, berhenti di sana, itu berhasil! Transfer ke sana tidak sulit. Tetapi bagaimana cara memverifikasi bahwa gambar manajer ternyata berada dalam bentuk yang sama seperti di registri kami? Tapi tidak mungkin! Oleh karena itu, saya hanya mengunggah gambar ke penyimpanan bersama, diunduh menggunakan perintah penyimpanan buruh pelabuhan, dan membagikan tautan. Dan tenang ini.
Pada hari keempat liburan, cukup bosan dengan mereka, gagasan untuk mengunduh dan merakit gambar buruh pelabuhan dengan benar menyalip saya lagi, dan saya terjun ke kode moby selama beberapa jam.
Apa yang saya miliki saat ini:
- Memahami cara mendapatkan semua layer
Mengambil Python "di tangan" dan berdasarkan pada skrip ini, saya memutuskan untuk memperbaikinya. Pada hari kedua, saya memutuskan untuk menulis naskah dari awal. Mengingat kerajinan saya untuk otorisasi-oauth, saya hanya menyalin bagian dari kode dari sana, ditambah perkembangan yang sudah saya lakukan ketika mengedit skrip. Tidak ada masalah dengan otorisasi dan mengunduh data ini, tetapi muncul pertanyaan:
- apa hash yang ditampilkan ketika perintah menarik buruh pelabuhan dijalankan?
- apa hash yang digunakan untuk memberi nama direktori di dalam tarball gambar?
- Bagaimana cara membuat arsip tar sehingga jumlah cek sesuai dengan gambar asli?
Untuk belajar, saya memilih gambar ubuntu: 18.04
gambar sha256sum disimpan melalui docker save
- 257cab9137419a53359d0ed76f680fe926ed3645238357bdcdb84070a8f26cd0.
> docker pull ubuntu:18.04 18.04: Pulling from library/ubuntu 2746a4a261c9: Downloading [==============> ] 6.909MB/26.69MB 4c1d20cdee96: Download complete 0d3160e1d0de: Download complete c8e37668deea: Download complete Digest: sha256:250cc6f3f3ffc5cdaa9d8f4946ac79821aafb4d3afc93928f0de9336eba21aa4 Status: Downloaded newer image for ubuntu:18.04 docker.io/library/ubuntu:18.04
Konten tarbal gambar
tar tvf ubuntu.tar drwxr-xr-x 0 root root 0 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/ -rw-r--r-- 0 root root 3 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/VERSION -rw-r--r-- 0 root root 477 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/json -rw-r--r-- 0 root root 991232 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/layer.tar drwxr-xr-x 0 root root 0 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/ -rw-r--r-- 0 root root 3 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/VERSION -rw-r--r-- 0 root root 477 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/json -rw-r--r-- 0 root root 15872 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/layer.tar -rw-r--r-- 0 root root 3411 Dec 19 11:21 549b9b86cb8d75a2b668c21c50ee092716d070f129fd1493f95ab7e43767eab8.json drwxr-xr-x 0 root root 0 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/ -rw-r--r-- 0 root root 3 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/VERSION -rw-r--r-- 0 root root 1264 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/json -rw-r--r-- 0 root root 3072 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/layer.tar drwxr-xr-x 0 root root 0 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/ -rw-r--r-- 0 root root 3 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/VERSION -rw-r--r-- 0 root root 401 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/json -rw-r--r-- 0 root root 65571328 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/layer.tar -rw-r--r-- 0 root root 432 Jan 1 1970 manifest.json -rw-r--r-- 0 root root 88 Jan 1 1970 repositories
Konfigurasi gambar
{ ... "rootfs": { "type": "layers", "diff_ids": [ "sha256:2dc9f76fb25b31e0ae9d36adce713364c682ba0d2fa70756486e5cedfaf40012", "sha256:9f3bfcc4a1a8a676da07287a1aa6f2dcc8e869ea6f054c337593481a5bb1345e", "sha256:27dd43ea46a831c39d224e7426794145fba953cd7309feccf4d5ea628072f6a2", "sha256:918efb8f161b4cbfa560e00e8e0efb737d7a8b00bf91bb77976257cd0014b765" ] } ... }
Pertanyaan pertama diselesaikan dengan cukup cepat, dokumentasi https://github.com/opencontainers/image-spec/blob/master/config.md membantu. Hash yang muncul ketika Anda menjalankan perintah pull docker adalah chainIDs dihitung dari daftar diff_ids dari manifes config-gambar, di mana chainID pertama selalu yang pertama dari daftar diff_ids, dan yang berikutnya adalah jumlah hash dari string (chain_id[i-1] + " " + diff_id[i])
. Kode untuk membangun chainID chainID:
def chain_ids(ids: list) -> list: chain = list() chain.append(ids[0]) if len(ids) < 2: return ids nxt = list() nxt.append("sha256:" + hashlib.sha256(f'{ids[0]} {ids[1]}'.encode()).hexdigest()) nxt.extend(ids[2:]) chain.extend(chain_ids(nxt)) return chain
Menambahkan awalan dengan nama algoritma, dalam hal ini "sha256:", adalah wajib dan termasuk dalam persyaratan standar opencontainers, mis. string harus dalam bentuk "algoritma: hash".
Dia menghabiskan dua malam pada pertanyaan tentang penamaan direktori. Untuk waktu yang cukup lama saya melihat kode sumber dari docker-daemon dan Oh! keajaiban! Saya berhasil menemukan kode generasi di sini dan di sini . Untuk menghasilkan nama direktori, Anda perlu menghitung hash dari konfigurasi json layer. Docker memiliki beberapa versi konfigurasi dan sebelum mesin docker 1.9, konfigurasi versi v1 digunakan. Tidak lebih cepat dikatakan daripada dilakukan! Dan lagi, siluet Nelson muncul. Setelah debug singkat saya menyadari bahwa masalahnya bersembunyi di generasi json. Dalam Python, urutan data dalam kamus mungkin berbeda dari urutan data dalam json yang dihasilkan dari kamus ini. Urutan data di json akan berbeda, dan sesuai hashnya juga akan berbeda. Saya harus pergi ke OrderedDict, mendaftar terlebih dahulu urutan data yang diinginkan di dalamnya. Ini meningkatkan ukuran kode sebanyak satu setengah kali.
Tampaknya semuanya sudah diperbaiki, saya menjalankan skrip dan ... di suatu tempat jauh di dalam, HA-HA terkenal muncul! Hash terakhir tidak cocok. Sekali lagi saya mempelajari kode dan melihat , dan ini adalah v1-config lain yang berisi semua informasi tentang gambar, yang dapat dilihat menggunakan docker inspect
. Tambahkan OrderDict lain khusus untuknya, lengkapi kodenya dan ... HA HA!
Sudah jam 5 pagi dan kepala saya tidak benar-benar berpikir, jadi setelah tidur saya kembali melihat kode. Berkali-kali melihat kode pembangkitan menemukan sebuah garis . Betapa senangnya saya melihat itu. Sebelum saya melihatnya, ada pemikiran untuk membangun buruh pelabuhan saya Jack hitam dan pencatatan data. Saya mengaktifkan debug, menjalankan docker save
dan ... Ini sama sekali tidak konyol, di docker-desktop untuk mac os ada batas pada panjang garis dalam log 947 karakter dan konfigurasi yang dihasilkan istirahat ke \"
. Setelah melakukan semua langkah ini di Linux, saya berhasil mendapatkan konfigurasi lapisan versi pertama, atas dasar itu saya menulis kode, dan saya berhasil mendapatkan hash yang diinginkan dari lapisan terakhir. hash untuk semua file adalah sama, direktori diberi nama dengan cara yang sama seperti gambar asli. Ini waktunya untuk mengumpulkan arsip tar ... HAHA!
Ukuran file tidak cocok, baca https://github.com/opencontainers/image-spec/blob/master/layer.md dan format arsip tar . Nilai default adalah 10240 byte, dan ukuran arsip yang saya kumpulkan adalah 9216 byte lebih besar. Pada awalnya saya berpikir bahwa perlu untuk mengurangi ukuran blok menjadi 1024 byte, yang ternyata tidak benar dan akibatnya, ukuran blok 512 byte menyamakan ukuran arsip.
tarfile.RECORDSIZE = 512
Baris pertama dari arsip yang baru dibuat berisi folder root "/". Opsi ini tidak cocok, oleh karena itu, saya menambah kode dengan memindai isi folder dan menambahkannya secara individual ke arsip, setelah sebelumnya mengurutkannya.
Akhirnya, kami berhasil mencapai ukuran file yang sama, tampilan direktori yang seragam, tetapi ini belum semuanya. File dan direktori, dengan pengecualian manifest.json dan respoitories, dalam arsip harus memiliki atribut st_atime, st_mtime sama dengan st_ctime. Untuk file manifest.json dan respoitories, atribut st_atime, st_mtime, dan st_ctime harus diberi tanggal pada awal era 1970-01-01 00:00
. Semua tanggal harus ditetapkan sesuai dengan zona waktu masing-masing. Karena saya melakukan semua pekerjaan di mac os, saya perhatikan satu perbedaan. Saat menyimpan gambar ke Linux, daftar file dalam arsip tampak seperti ini:
tar tvf ubuntu.tar drwxr-xr-x 0/0 0 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/ -rw-r--r-- 0/0 3 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/VERSION -rw-r--r-- 0/0 477 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/json -rw-r--r-- 0/0 991232 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/layer.tar drwxr-xr-x 0/0 0 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/ -rw-r--r-- 0/0 3 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/VERSION -rw-r--r-- 0/0 477 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/json -rw-r--r-- 0/0 15872 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/layer.tar -rw-r--r-- 0/0 3411 Dec 19 11:21 549b9b86cb8d75a2b668c21c50ee092716d070f129fd1493f95ab7e43767eab8.json drwxr-xr-x 0/0 0 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/ -rw-r--r-- 0/0 3 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/VERSION -rw-r--r-- 0/0 1264 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/json -rw-r--r-- 0/0 3072 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/layer.tar drwxr-xr-x 0/0 0 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/ -rw-r--r-- 0/0 3 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/VERSION -rw-r--r-- 0/0 401 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/json -rw-r--r-- 0/0 65571328 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/layer.tar -rw-r--r-- 0/0 432 Jan 1 1970 manifest.json -rw-r--r-- 0/0 88 Jan 1 1970 repositories
Berbeda dengan daftar di awal artikel, di Linux, arsip disimpan dengan bendera numerik saja. Ada dua variabel dalam objek tarinfo yang bertanggung jawab untuk ini, tarinfo.uname dan tarinfo.gname. Dan masalah kedua dengan mac os adalah kurangnya grup root, itu diperbaiki menggunakan variabel tarinfo.gid dalam objek tarinfo yang sama. Yah, semuanya tampaknya membuat arsip ...

Untuk semua file, hash konvergen, nama direktori dan file adalah sama, atribut st_atime, st_mtime dan st_ctime menyatu dengan yang asli, hak atas file sama persis. Membuka kedua arsip dalam hex editor melihat sedikit perbedaan:

Jendela atas adalah yang asli, arsip yang lebih rendah telah saya kumpulkan.
Memahami format tar. Setelah nama direktori adalah nilai hak atas file (persegi panjang oranye). Perbedaannya adalah bahwa informasi tentang objek yang ditambahkan ke arsip tidak ditambahkan ke hak direktori. Nilai 40755 yang ditunjukkan dalam hak menunjukkan bahwa ini adalah direktori dengan izin 755, dan 100644 adalah file dengan hak 644. Persegi panjang merah adalah string-ajaib dan dinilai oleh kode tarfile, string-string ustar\000
, hanya digunakan dalam format PAX dan USTAR. Format PAX sama sekali tidak cocok, ia menggunakan jenis header khusus. Kotak biru adalah jumlah cek dan berbeda karena penggunaan berbagai format untuk hak penulisan file dan header-ajaib.
Saya mengalihkan format arsip ke USTAR, tetapi tidak jelas apa yang harus dilakukan dengan merekam izin file. Di sini dan di sini keajaiban terjadi bagi saya, saya tidak pernah bekerja dengan sistem oktal dan saya tidak mengerti mengapa ampersand diperlukan di sini (mungkin seseorang di komentar akan berbagi pengetahuan). Saya harus menambahkan beberapa cetakan untuk melihat data apa yang muncul dengan argumen dan data apa yang digunakan untuk membentuk blok arsip. Mengambil bilangan bulat dari posisi kedua dari blok data, itu adalah 16877, dan membawanya ke kalkulus oktal, ternyata nilai ini adalah 0o40755
, yang 0o40755
seperti yang saya butuhkan. Hanya mengesampingkan fungsi get_info dan _create_header, menghapus & 0o7777
dari mereka (tidak ada yang terlintas di pikiran saya), saya berhasil mengumpulkan arsip tar dengan hash sha256 yang bertepatan dengan yang asli.
PS Saat menulis artikel, gambar ubuntu telah diperbarui: 18,04 di hub.docker.com. Jadi saya harus mengunduh gambar di Digest. Jumlah hash tidak lagi cocok dengan aslinya karena fakta bahwa Digest ditulis sebagai ganti tag, jika tidak mereka adalah gambar yang identik.
Penemuan kedua bagi saya adalah tidak adanya file repositori di arsip saat menyimpan gambar dengan tag yang hilang menggunakan docker save
.
Kode kerja lengkap di sini: https://github.com/myback/docker_pull
Gambar Nelson Manz, serta tawanya "HA-HA" adalah milik FOX :)