Experimentovali jste někdy s kódem nebo systémovými utilitami v Linux Abyste se nemuseli starat o základní systém a zničit všechno, pokud se v kódu objeví chyba, kterou je třeba spustit s root oprávněními?
Ale co skutečnost, že řekněme, že potřebujete otestovat nebo spustit celý cluster různých mikroslužeb na jednom počítači? Sto nebo dokonce tisíc?
Virtuální počítače spravované hypervizorem by mohly být schopny takové problémy vyřešit, ale za jakou cenu? Například kontejner LXD založený na distribuci Alpine. Linux spotřebuje minimum všeho 7.60MB RAM a kde se kořenový oddíl po spuštění zabírá 9.5MB! Jak se ti to líbí, Elone Musku? Doporučuji zkontrolovat základní funkce LXD - kontejnerového systému v Linux
Poté, co bylo obecně jasné, co jsou LXD kontejnery, pojďme dále a zamysleme se nad tím, co kdyby existovala taková platforma harvesteru, kde byste mohli bezpečně spouštět kód pro hostitele, generovat grafy, dynamicky (interaktivně) propojovat UI-widgety s vaším kódem, doplnit kód textem o blackjack... formátování? Nějaký interaktivní blog? Páni... chci to! Chtějte! 🙂
Podívejte se pod kočku, kde spustíme v kontejneru jupyterová laboratoř - nová generace uživatelského rozhraní namísto zastaralého Jupyter Notebooku a nainstalujeme také moduly Pythonu jako např. nemotorný, Pandy, matplotlib, IPyWidgets což vám umožní udělat vše výše uvedené a uložit to vše do speciálního souboru - notebooku IPython.

Navigace
- Orbitální plán vzletu
- Instalace a konfigurace základního systému
- Instalace základního softwaru a nastavení systému
- Instalace a konfigurace JupyterLab
- Sdílení dat s hostitelem
- Ahoj světe!
- Rozšíření možností Pythonu
- Testování modulů v JupyterLab
- Co jiného?
Orbitální plán vzletu ^

Pojďme si nastínit stručný akční plán, který nám usnadní implementaci výše uvedeného schématu:
- Pojďme nainstalovat a spustit kontejner založený na distribuční sadě Vysokohorský Linux. Tuto distribuci využijeme, protože je zaměřena na minimalismus a nainstaluje do ní pouze nejnutnější software, nic nadbytečného.
- Pojďme do kontejneru přidat další virtuální disk a pojmenovat jej -
hostfsa připojte jej ke kořenovému systému souborů. Tento disk umožní používat soubory na hostiteli z daného adresáře uvnitř kontejneru. Naše data tedy budou nezávislá na kontejneru. Pokud je kontejner smazán, data zůstanou na hostiteli. Toto schéma je také užitečné pro sdílení stejných dat mezi mnoha kontejnery bez použití standardních síťových mechanismů distribuce kontejnerů. - Pojďme nainstalovat Bash, sudo, potřebné knihovny, přidat a nakonfigurovat uživatele systému
- Pojďme si nainstalovat Python, moduly a zkompilovat pro ně binární závislosti
- Pojďme nainstalovat a spustit jupyterová laboratoř, přizpůsobte vzhled, nainstalujte pro něj rozšíření.
V tomto článku začneme spuštěním kontejneru, nebudeme uvažovat o instalaci a konfiguraci LXD, to vše najdete v jiném článku - Základní funkce LXD, kontejnerového systému v Linux.
Instalace a konfigurace základního systému ^
Kontejner vytvoříme příkazem, ve kterém určíme obrázek - alpine3, identifikátor pro kontejner - jupyterlab a v případě potřeby konfigurační profily:
lxc init alpine3 jupyterlab --profile=default --profile=hddrootZde používám konfigurační profil hddroot což určuje vytvoření kontejneru s kořenovým oddílem Skladovací bazén umístěné na fyzickém HDD disku:
lxc profile show hddroot
config: {}
description: ""
devices:
root:
path: /
pool: hddpool
type: disk
name: hddroot
used_by: []lxc storage show hddpool
config:
size: 10GB
source: /dev/loop1
volatile.initial_source: /dev/loop1
description: ""
name: hddpool
driver: btrfs
used_by:
- /1.0/images/ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3
- /1.0/profiles/hddroot
status: Created
locations:
- noneTo mi dává možnost experimentovat s kontejnery na HDD disku a šetřit tak zdroje SSD disku, který je také dostupný v mém systému 🙂 pro který jsem vytvořil samostatný konfigurační profil ssdroot.
Po vytvoření je kontejner ve stavu STOPPED, takže jej musíme spustit spuštěním systému init v něm:
lxc start jupyterlabZobrazme seznam kontejnerů v LXD pomocí klávesy -c což naznačuje které czobrazení sloupců:
lxc list -c ns4b
+------------+---------+-------------------+--------------+
| NAME | STATE | IPV4 | STORAGE POOL |
+------------+---------+-------------------+--------------+
| jupyterlab | RUNNING | 10.0.5.198 (eth0) | hddpool |
+------------+---------+-------------------+--------------+Při vytváření kontejneru byla IP adresa vybrána náhodně, protože jsme použili konfigurační profil default který byl dříve nakonfigurován v článku Základní funkce LXD, kontejnerového systému v Linux.
Tuto IP adresu změníme na lépe zapamatovatelnou vytvořením síťového rozhraní na úrovni kontejneru, nikoli na úrovni konfiguračního profilu, jak je tomu nyní v aktuální konfiguraci. Nemusíte to dělat, můžete to přeskočit.
Vytvoření síťového rozhraní eth0 který propojíme s přepínačem (síťovým mostem) lxdbr0 ve kterém jsme povolili NAT podle předchozího článku a kontejner bude mít nyní přístup k internetu a rozhraní také přiřadíme statickou IP adresu - 10.0.5.5:
lxc config device add jupyterlab eth0 nic name=eth0 nictype=bridged parent=lxdbr0 ipv4.address=10.0.5.5Po přidání zařízení je nutné kontejner restartovat:
lxc restart jupyterlabKontrola stavu kontejneru:
lxc list -c ns4b
+------------+---------+------------------+--------------+
| NAME | STATE | IPV4 | STORAGE POOL |
+------------+---------+------------------+--------------+
| jupyterlab | RUNNING | 10.0.5.5 (eth0) | hddpool |
+------------+---------+------------------+--------------+Instalace základního softwaru a nastavení systému ^
Chcete-li spravovat náš kontejner, musíte nainstalovat následující software:
Balíček
Popis
praštit
Shell GNU Bourne Again
bash-dokončení
Programovatelné dokončení pro bash shell
sudo
Dejte určitým uživatelům možnost spouštět některé příkazy jako root
stín
Sada nástrojů pro správu hesel a účtů s podporou stínových souborů a PAM
tzdata
Zdroje dat pro časové pásmo a letní čas
nano
Klon editoru Pico s vylepšeními
Kromě toho můžete nainstalovat podporu do systémových manuálových stránek instalací následujících balíčků − man man-pages mdocml-apropos less
lxc exec jupyterlab -- apk add bash bash-completion sudo shadow tzdata nanoPodívejme se na příkazy a klávesy, které jsme použili:
lxc— Zavolejte klienta LXDexec- Metoda klienta LXD, která spouští příkaz v kontejnerujupyterlab— ID kontejneru--- Speciální klíč, který určuje, že další klíče nebudou interpretovány jako klíče prolxca předejte zbytek provázku tak, jak je, do nádobyapk— Správce distribučních balíčků Alpine Linuxadd— Metoda správce balíčků, která instaluje balíčky zadané za příkazem
Dále v systému nastavíme časové pásmo Europe/Moscow:
lxc exec jupyterlab -- cp /usr/share/zoneinfo/Europe/Moscow /etc/localtimePo instalaci časového pásma balíček tzdata již není v systému potřeba, bude zabírat místo, takže jej smažte:
lxc exec jupyterlab -- apk del tzdataKontrola časového pásma:
lxc exec jupyterlab -- date
Wed Apr 15 10:49:56 MSK 2020Abychom ušetřili čas při nastavování Bashu pro nové uživatele v kontejneru, zkopírujeme do něj připravené skel soubory z hostitelského systému. To nám umožní přizpůsobit Bash v kontejneru v interaktivním režimu. Můj hostitelský systém je Manjaro. Linux a zkopírované soubory /etc/skel/.bash_profile, /etc/skel/.bashrc, /etc/skel/.dir_colors v principu pasují na Alpine Linux a nezpůsobují kritické problémy, ale můžete mít jinou distribuci a budete muset sami zjistit, zda se při spuštění Bash v kontejneru vyskytla chyba.
Zkopírujte soubory Skel do kontejneru. Klíč --create-dirs vytvoří potřebné adresáře, pokud neexistují:
lxc file push /etc/skel/.bash_profile jupyterlab/etc/skel/.bash_profile --create-dirs
lxc file push /etc/skel/.bashrc jupyterlab/etc/skel/.bashrc
lxc file push /etc/skel/.dir_colors jupyterlab/etc/skel/.dir_colorsPro stávajícího uživatele root zkopírujte soubory skel právě zkopírované do kontejneru do domovského adresáře:
lxc exec jupyterlab -- cp /etc/skel/.bash_profile /root/.bash_profile
lxc exec jupyterlab -- cp /etc/skel/.bashrc /root/.bashrc
lxc exec jupyterlab -- cp /etc/skel/.dir_colors /root/.dir_colorsV alpském prostředí Linux pro uživatele je nainstalován systémový shell /bin/sh, nahradíme jej root uživatel v Bash:
lxc exec jupyterlab -- usermod --shell=/bin/bash rootŽe root uživatel nebyl bez hesla, potřebuje heslo nastavit. Následující příkaz mu vygeneruje a nastaví nové náhodné heslo, které po jeho provedení uvidíte na obrazovce konzole:
lxc exec jupyterlab -- /bin/bash -c "PASSWD=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 12); echo "root:$PASSWD" | chpasswd && echo "New Password: $PASSWD""
New Password: sFiXEvBswuWAVytvořme také nového uživatele systému - jupyter pro které budeme konfigurovat později jupyterová laboratoř:
lxc exec jupyterlab -- useradd --create-home --shell=/bin/bash jupyterPojďme si pro něj vygenerovat a nastavit heslo:
lxc exec jupyterlab -- /bin/bash -c "PASSWD=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 12); echo "jupyter:$PASSWD" | chpasswd && echo "New Password: $PASSWD""
New Password: ZIcbzWrF8tkiDále provedeme dva příkazy, první vytvoří systémovou skupinu sudoa druhý do něj přidá uživatele jupyter:
lxc exec jupyterlab -- groupadd --system sudo
lxc exec jupyterlab -- groupmems --group sudo --add jupyterPodívejme se, do jakých skupin uživatel patří jupyter:
lxc exec jupyterlab -- id -Gn jupyter
jupyter sudoVšechno je v pořádku, jedeme dál.
Povolit všechny uživatele, kteří jsou členy skupiny sudo použít příkaz sudo. Chcete-li to provést, spusťte následující skript, kde sed odkomentuje řádek parametrů v konfiguračním souboru /etc/sudoers:
lxc exec jupyterlab -- /bin/bash -c "sed --in-place -e '/^#[ t]*%sudo[ t]*ALL=(ALL)[ t]*ALL$/ s/^[# ]*//' /etc/sudoers"Instalace a konfigurace JupyterLab ^
jupyterová laboratoř je aplikace Python, takže musíme nejprve nainstalovat tento interpret. Taky, jupyterová laboratoř nainstalujeme pomocí správce balíčků Pythonu pip, a ne ten systémový, protože může být v systémovém úložišti zastaralý, a proto pro něj musíme ručně vyřešit závislosti instalací následujících balíčků − python3 python3-dev gcc libc-dev zeromq-dev:
lxc exec jupyterlab -- apk add python3 python3-dev gcc libc-dev zeromq-devPojďme aktualizovat moduly pythonu a správce balíčků pip na aktuální verzi:
lxc exec jupyterlab -- python3 -m pip install --upgrade pip setuptools wheelSada jupyterová laboratoř přes správce balíčků pip:
lxc exec jupyterlab -- python3 -m pip install jupyterlabOd rozšíření v jupyterová laboratoř jsou experimentální a nejsou oficiálně dodávány s balíčkem jupyterlab, takže je musíme nainstalovat a nakonfigurovat ručně.
Nainstalujme NodeJS a pro něj správce balíčků - NPM, od jupyterová laboratoř používá je pro svá rozšíření:
lxc exec jupyterlab -- apk add nodejs npmK rozšířením pro jupyterová laboratoř které nainstalujeme fungovaly, je potřeba je nainstalovat do uživatelského adresáře, protože se aplikace spouští od uživatele jupyter. Problém je v tom, že v příkazu launch není žádný parametr, který by bylo možné předat do adresáře, aplikace přijímá pouze proměnnou prostředí, a proto ji musíme definovat. K tomu napíšeme příkaz export proměnné JUPYTERLAB_DIR v uživatelském prostředí jupyter, do souboru .bashrckterý se provede pokaždé, když se uživatel přihlásí:
lxc exec jupyterlab -- su -l jupyter -c "echo -e "nexport JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab" >> .bashrc"Další příkaz nainstaluje speciální rozšíření - správce rozšíření jupyterová laboratoř:
lxc exec jupyterlab -- su -l jupyter -c "export JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab; jupyter labextension install --no-build @jupyter-widgets/jupyterlab-manager"Nyní je vše připraveno k prvnímu spuštění jupyterová laboratoř, ale stále můžeme nainstalovat několik užitečných rozšíření:
toc— Obsah, generuje seznam nadpisů v článku/zápisníkujupyterlab-horizon-theme— Téma uživatelského rozhraníjupyterlab_neon_theme— Téma uživatelského rozhraníjupyterlab-ubu-theme- Další téma od autora tento článek :) Ale v tomto případě se ukáže instalace z úložiště GitHub
Chcete-li nainstalovat tato rozšíření, spusťte postupně následující příkazy:
lxc exec jupyterlab -- su -l jupyter -c "export JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab; jupyter labextension install --no-build @jupyterlab/toc @mohirio/jupyterlab-horizon-theme @yeebc/jupyterlab_neon_theme"lxc exec jupyterlab -- su -l jupyter -c "wget -c https://github.com/microcoder/jupyterlab-ubu-theme/archive/master.zip"lxc exec jupyterlab -- su -l jupyter -c "unzip -q master.zip && rm master.zip"lxc exec jupyterlab -- su -l jupyter -c "export JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab; jupyter labextension install --no-build jupyterlab-ubu-theme-master"lxc exec jupyterlab -- su -l jupyter -c "rm -r jupyterlab-ubu-theme-master"Po instalaci rozšíření je musíme zkompilovat, protože dříve jsme při instalaci specifikovali klíč --no-build ušetřit čas. Nyní výrazně urychlíme tím, že je sestavíme najednou:
lxc exec jupyterlab -- su -l jupyter -c "export JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab; jupyter lab build"Nyní spusťte následující dva příkazy, abyste jej spustili poprvé jupyterová laboratoř. Bylo by možné jej spustit jedním příkazem, ale v tomto případě si příkaz ke spuštění, který si v duchu těžko pamatujete, zapamatuje bash v kontejneru a ne na hostiteli, kde je již příkazů dostatek zapsat je do historie :)
Přihlaste se do kontejneru jako uživatel jupyter:
lxc exec jupyterlab -- su -l jupyterDále běž jupyterová laboratoř s klíči a parametry, jak je uvedeno:
[jupyter@jupyterlab ~]$ jupyter lab --ip=0.0.0.0 --no-browserPřejděte na adresu ve webovém prohlížeči http://10.0.5.5:8888 a na stránce, která se otevře, zadejte známka přístup, který uvidíte v konzole. Zkopírujte a vložte jej na stránku a poté klikněte Přihlášení. Po přihlášení přejděte do nabídky rozšíření vlevo, jak je znázorněno na obrázku níže, kde budete při aktivaci správce rozšíření vyzváni k přijetí bezpečnostních rizik instalací rozšíření od třetích stran, pro které je příkaz Vývoj JupyterLab není odpovědný:

Celé to však izolujeme jupyterová laboratoř a umístěte jej do kontejneru, aby rozšíření třetích stran, která vyžadují a používají NodeJS, nemohla alespoň ukrást data na disku jiná než ta, která otevřeme uvnitř kontejneru. Získejte své soukromé dokumenty na hostiteli v /home procesy z kontejneru pravděpodobně neuspějí, a pokud ano, pak musíte mít oprávnění k souborům v hostitelském systému, protože kontejner spouštíme v neprivilegovaný režim. Na základě těchto informací můžete posoudit riziko zahrnutí rozšíření do jupyterová laboratoř.
Vytvořené notebooky IPython (stránky v jupyterová laboratoř) bude nyní vytvořen v domovském adresáři uživatele - /home/jupyter, ale naše plány jsou rozdělit data (sdílet) mezi hostitele a kontejner, takže se vraťte do konzole a zastavte jupyterová laboratoř spuštěním klávesové zkratky - CTRL+C a odpovídání y na požádání. Poté ukončete interaktivní relaci uživatele jupyter dokončení horké klávesy CTRL+D.
Sdílení dat s hostitelem ^
Chcete-li sdílet data s hostitelem, musíte v kontejneru vytvořit zařízení, které vám to umožní, a za tímto účelem spusťte následující příkaz, kde zadáme následující klíče:
lxc config device add— Příkaz přidá konfiguraci zařízeníjupyter— ID kontejneru, do kterého je konfigurace přidánahostfs- ID zařízení. Můžete nastavit libovolný název.disk— Je uveden typ zařízenípath— Určuje cestu v kontejneru, ke kterému LXD připojí toto zařízenísource— Zadejte zdroj, cestu k adresáři na hostiteli, který chcete sdílet s kontejnerem. Určete cestu podle svých preferencí
lxc config device add jupyterlab hostfs disk path=/mnt/hostfs source=/home/dv/projects/ipython-notebooksPro katalog /home/dv/projects/ipython-notebooks oprávnění musí být nastaveno na uživatele kontejneru, který má aktuálně UID rovné SubUID + UID, viz kapitola Bezpečnost. Kontejnerová privilegia v článku Základní funkce LXD, kontejnerového systému v Linux.
Nastavte oprávnění na hostiteli, kde vlastníkem bude uživatel kontejneru jupytera proměnná $USER určí vašeho hostitele jako skupinu:
sudo chown 1001000:$USER /home/dv/projects/ipython-notebooksAhoj světe! ^
Pokud máte stále otevřenou relaci konzoly v kontejneru s jupyterová laboratořa poté jej restartujte s novým klíčem --notebook-dir nastavením hodnoty /mnt/hostfs jako cesta ke kořenovému adresáři notebooků v kontejneru pro zařízení, které jsme vytvořili v předchozím kroku:
jupyter lab --ip=0.0.0.0 --no-browser --notebook-dir=/mnt/hostfsPoté přejděte na stránku http://10.0.5.5:8888 a vytvořte si svůj první notebook kliknutím na tlačítko na stránce, jak je znázorněno na obrázku níže:

Poté do pole na stránce zadejte kód Pythonu, který zobrazí klasiku Hello World!. Po dokončení zadávání stiskněte CTRL+ENTER nebo tlačítko „přehrát“ na panelu nástrojů v horní části, aby JupyterLab provedl toto:

V tuto chvíli je téměř vše připraveno k použití, ale nebude zajímavé, pokud nebudeme instalovat další moduly Pythonu (plnohodnotné aplikace), které mohou výrazně rozšířit standardní možnosti Pythonu v jupyterová laboratoř, takže jdeme dál :)
PS Zajímavé je, že stará implementace jupyter pod kódovým jménem Jupyter Notebook nezmizelo a existuje paralelně s jupyterová laboratoř. Chcete-li přejít na starou verzi, klikněte na odkaz přidáním přípony do adresy/tree, a přechod na novou verzi se provede s příponou /lab, ale nemusí být specifikováno:
- Jupyter Notebook - http://10.0.5.5:8888/tree
- Jupyter Lab - http://10.0.5.5:8888/lab
Rozšíření možností Pythonu ^
V této sekci nainstalujeme tak výkonné moduly jazyka Python jako nemotorný, Pandy, matplotlib, IPyWidgets jehož výsledky jsou integrovány do notebooků jupyterová laboratoř.
Před instalací uvedených modulů Pythonu prostřednictvím správce balíčků pip Nejprve musíme vyřešit systémové závislosti v Alpine. Linux:
g++— Potřebné pro kompilaci modulů, protože některé z nich jsou implementovány v jazyce C + + a připojit se k Pythonu za běhu jako binární modulyfreetype-dev- závislost na modulu Python matplotlib
Instalace závislostí:
lxc exec jupyterlab -- apk add g++ freetype-devSe současným stavem alpského rozšíření je jeden problém. Linux Nemohu zkompilovat novou verzi NumPy; Zobrazí se mi chyba kompilace, kterou nedokážu vyřešit:
CHYBA: Nelze vytvořit kola pro numpy, která používají PEP 517 a nelze je nainstalovat přímo
Proto nainstalujeme tento modul jako systémový balíček, který distribuuje již zkompilovanou verzi, ale o něco starší, než je aktuálně dostupná na webu:
lxc exec jupyterlab -- apk add py3-numpy py3-numpy-devDále nainstalujte moduly Pythonu prostřednictvím správce balíčků pip. Buďte prosím trpěliví, protože některé moduly se zkompilují a může to trvat několik minut. Na mém počítači trvala kompilace ~15 minut:
lxc exec jupyterlab -- python3 -m pip install pandas ipywidgets matplotlibVymazání mezipaměti instalace:
lxc exec jupyterlab -- rm -rf /home/*/.cache/pip/*
lxc exec jupyterlab -- rm -rf /root/.cache/pip/*Testování modulů v JupyterLab ^
Pokud běžíte jupyterová laboratoř, restartujte jej, aby se aktivovaly nově nainstalované moduly. Chcete-li to provést, v relaci konzoly klepněte na CTRL+C kde to máte spuštěné a vstupte y pro zastavení požadavku a následné spuštění znovu jupyterová laboratoř stisknutím šipky nahoru na klávesnici, aby se příkaz nezadával znovu a pak Enter pro spuštění:
jupyter lab --ip=0.0.0.0 --no-browser --notebook-dir=/mnt/hostfsPřejít na stránku http://10.0.5.5:8888/lab nebo obnovte stránku v prohlížeči a poté zadejte následující kód do nové buňky poznámkového bloku:
%matplotlib inline
from ipywidgets import interactive
import matplotlib.pyplot as plt
import numpy as np
def f(m, b):
plt.figure(2)
x = np.linspace(-10, 10, num=1000)
plt.plot(x, m * x + b)
plt.ylim(-5, 5)
plt.show()
interactive_plot = interactive(f, m=(-2.0, 2.0), b=(-3, 3, 0.5))
output = interactive_plot.children[-1]
output.layout.height = '350px'
interactive_plotMěli byste získat výsledek jako na obrázku níže, kde IPyWidgets vygeneruje prvek uživatelského rozhraní na stránce, který interaktivně interaguje se zdrojovým kódem, a také matplotlib zobrazí výsledek kódu ve formě obrázku jako funkčního grafu:

Mnoho příkladů IPyWidgets najdete to v tutoriálech zde
Co jiného? ^
Dobře, pokud jste zůstali a dostali se až na konec článku. Schválně jsem na konec článku nedal hotový skript, který by se nainstaloval jupyterová laboratoř jedním kliknutím povzbudíte pracovníky :) Ale můžete to udělat sami, protože už víte jak, po shromáždění příkazů do jediného Bash skriptu :)
Můžete také:
- Nastavte síťový název kontejneru místo IP adresy tak, že jej jednoduše zapíšete
/etc/hostsa zadejte adresu do prohlížeče http://jupyter.local:8888 - Pohrajte si s limitem zdrojů pro kontejner, k tomu si přečtěte kapitolu základní schopnosti LXD nebo získat více informací na vývojářských stránkách LXD.
- Změňte téma:

A mnohem víc můžete udělat! To je vše. Přeji ti úspěch!
AKTUALIZACE: 15.04.2020 18:30 - Opraveny chyby v kapitole „Ahoj, světe!“
AKTUALIZACE: 16.04.2020/10/00 XNUMX:XNUMX — Opraven a doplněn text v popisu aktivace správce rozšíření jupyterová laboratoř
AKTUALIZACE: 16.04.2020/10/40 XNUMX:XNUMX — Opraveny chyby nalezené v textu a mírně změněny k lepšímu v kapitole „Instalace základního softwaru a nastavení systému“
Zdroj: www.habr.com
