Część 5: Hello Containers¶
Tłumaczenie wspomagane przez AI - dowiedz się więcej i zasugeruj ulepszenia
W Częściach 1-4 tego kursu nauczyłeś się używać podstawowych elementów budulcowych Nextflow do składania prostego workflow zdolnego do przetwarzania tekstu, równoległego wykonywania wielu wejść i zbierania wyników do dalszego przetwarzania.
Jednak byłeś ograniczony do podstawowych narzędzi UNIX dostępnych w Twoim środowisku. Rzeczywiste zadania często wymagają różnych narzędzi i pakietów, które nie są domyślnie dołączone. Zazwyczaj musiałbyś zainstalować te narzędzia, zarządzać ich zależnościami i rozwiązywać konflikty.
To wszystko jest bardzo nużące i irytujące, więc pokażemy Ci, jak używać kontenerów, aby rozwiązać ten problem znacznie wygodniej.
Kontener to lekka, samodzielna, wykonywalna jednostka oprogramowania utworzona z obrazu, która zawiera wszystko potrzebne do uruchomienia aplikacji, w tym kod, biblioteki systemowe i ustawienia. Jak można się domyślić, będzie to bardzo pomocne w zwiększeniu powtarzalności Twoich pipeline.
Zauważ, że będziemy tego uczyć używając Docker, ale pamiętaj, że Nextflow obsługuje również kilka innych technologii kontenerowych.
Jak zacząć od tej sekcji
Ta sekcja kursu zakłada, że ukończyłeś Części 1-4 kursu Hello Nextflow i masz kompletny działający pipeline.
Jeśli zaczynasz kurs od tego miejsca, musisz skopiować katalog modules z rozwiązań:
0. Rozgrzewka: Uruchom hello-containers.nf¶
Użyjemy skryptu workflow hello-containers.nf jako punktu wyjścia.
Jest on równoważny skryptowi utworzonemu podczas pracy nad Częścią 4 tego szkolenia, z tą różnicą, że zmieniliśmy miejsca docelowe wyjść:
| hello-containers.nf | |
|---|---|
Aby upewnić się, że wszystko działa, uruchom skrypt raz przed wprowadzeniem jakichkolwiek zmian:
Wynik polecenia
Jak poprzednio, pliki wyjściowe znajdziesz w katalogu określonym w bloku output (results/hello_containers/).
Zawartość katalogu
Jeśli to zadziałało, jesteś gotowy do nauki używania kontenerów.
1. Użyj kontenera 'ręcznie'¶
Chcemy dodać krok do naszego workflow, który będzie używał kontenera do wykonania.
Jednak najpierw omówimy podstawowe koncepcje i operacje, aby utrwalić Twoje zrozumienie tego, czym są kontenery, zanim zaczniemy ich używać w Nextflow.
1.1. Pobierz obraz kontenera¶
Aby użyć kontenera, zazwyczaj pobierasz lub ściągasz obraz z rejestru, a następnie uruchamiasz go, aby utworzyć działającą instancję.
Ogólna składnia jest następująca:
Część docker pull to instrukcja dla systemu kontenerowego, aby pobrał obraz kontenera z repozytorium.
Część '<kontener>' to adres URI obrazu kontenera.
Jako przykład pobierzmy obraz kontenera zawierający cowpy, pythonową implementację narzędzia o nazwie cowsay, które generuje grafikę ASCII do wyświetlania dowolnych tekstów wejściowych w zabawny sposób.
________________________
< Are we having fun yet? >
------------------------
\ ___-------___
\ _-~~ ~~-_
\ _-~ /~-_
/^\__/^\ /~ \ / \
/| O|| O| / \_______________/ \
| |___||__| / / \ \
| \ / / \ \
| (_______) /______/ \_________ \
| / / \ / \
\ \^\\ \ / \ /
\ || \______________/ _-_ //\__//
\ ||------_-~~-_ ------------- \ --/~ ~\ || __/
~-----||====/~ |==================| |/~~~~~
(_(__/ ./ / \_\ \.
(_(___/ \_____)_)
Istnieją różne repozytoria, w których można znaleźć opublikowane kontenery.
Użyliśmy usługi Seqera Containers do wygenerowania tego obrazu kontenera Docker z pakietu Conda cowpy: 'community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273'.
Uruchom pełne polecenie pobierania:
Wynik polecenia
1.1.5--3db457ae1977a273: Pulling from library/cowpy
dafa2b0c44d2: Pull complete
dec6b097362e: Pull complete
f88da01cff0b: Pull complete
4f4fb700ef54: Pull complete
92dc97a3ef36: Pull complete
403f74b0f85e: Pull complete
10b8c00c10a5: Pull complete
17dc7ea432cc: Pull complete
bb36d6c3110d: Pull complete
0ea1a16bbe82: Pull complete
030a47592a0a: Pull complete
c23bdb422167: Pull complete
e1686ff32a11: Pull complete
Digest: sha256:1ebc0043e8cafa61203bf42d29fd05bd14e7b4298e5e8cf986504c15f5aa4160
Status: Downloaded newer image for community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273
community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273
Jeśli nigdy wcześniej nie pobierałeś tego obrazu, może to zająć minutę. Po zakończeniu masz lokalną kopię obrazu kontenera.
1.2. Użyj kontenera do uruchomienia cowpy jako jednorazowego polecenia¶
Bardzo częstym sposobem używania kontenerów jest uruchamianie ich bezpośrednio, czyli nieinteraktywnie. To świetne rozwiązanie do uruchamiania jednorazowych poleceń.
Ogólna składnia jest następująca:
Część docker run --rm '<kontener>' to instrukcja dla systemu, aby uruchomił instancję z obrazu i wykonał w niej polecenie.
Flaga --rm mówi systemowi, aby usunął instancję po zakończeniu polecenia.
Składnia [polecenie narzędzia] zależy od używanego narzędzia i konfiguracji kontenera.
Zacznijmy po prostu od cowpy.
W pełni złożone polecenie wykonania kontenera wygląda tak; uruchom je:
Wynik polecenia
System uruchomił kontener, wykonał polecenie cowpy z jego parametrami, wysłał wynik do konsoli i na koniec wyłączył instancję kontenera.
1.3. Użyj kontenera do uruchomienia cowpy interaktywnie¶
Możesz również uruchomić kontener interaktywnie, co daje Ci wiersz poleceń wewnątrz kontenera i pozwala eksperymentować z poleceniem.
1.3.1. Uruchom kontener¶
Aby uruchomić interaktywnie, po prostu dodajemy -it do polecenia docker run.
Opcjonalnie możemy określić powłokę, której chcemy używać wewnątrz kontenera, dodając np. /bin/bash do polecenia.
Zauważ, że Twój wiersz poleceń zmienia się na coś w rodzaju (base) root@b645838b3314:/tmp#, co wskazuje, że jesteś teraz wewnątrz kontenera.
Możesz to sprawdzić, uruchamiając ls /, aby wylistować zawartość katalogu od korzenia systemu plików:
Wynik polecenia
Używamy tutaj ls zamiast tree, ponieważ narzędzie tree nie jest dostępne w tym kontenerze.
Widać, że system plików wewnątrz kontenera różni się od systemu plików na Twoim systemie hosta.
Jednym z ograniczeń tego, co właśnie zrobiliśmy, jest to, że kontener jest domyślnie całkowicie odizolowany od systemu hosta. Oznacza to, że kontener nie może uzyskać dostępu do żadnych plików na systemie hosta, chyba że wyraźnie mu na to pozwolisz.
Pokażemy Ci, jak to zrobić za chwilę.
1.3.2. Uruchom żądane polecenie(a) narzędzia¶
Teraz, gdy jesteś wewnątrz kontenera, możesz uruchomić polecenie cowpy bezpośrednio i podać mu parametry.
Na przykład dokumentacja narzędzia mówi, że możemy zmienić postać ('cowacter') za pomocą -c.
Wynik polecenia
Teraz wynik pokazuje pingwina Linuxa, Tuxa, zamiast domyślnej krowy, ponieważ określiliśmy parametr -c tux.
Ponieważ jesteś wewnątrz kontenera, możesz uruchamiać polecenie cowpy ile razy chcesz, zmieniając parametry wejściowe, bez konieczności zajmowania się poleceniami Docker.
Wskazówka
Użyj flagi '-c', aby wybrać inną postać, w tym:
beavis, cheese, daemon, dragonandcow, ghostbusters, kitty, moose, milk, stegosaurus, turkey, turtle, tux
To fajne. Jeszcze fajniej byłoby, gdybyśmy mogli podać nasz plik greetings.csv jako wejście.
Ale ponieważ nie mamy dostępu do systemu plików, nie możemy.
Naprawmy to.
1.3.3. Wyjdź z kontenera¶
Aby wyjść z kontenera, możesz wpisać exit w wierszu poleceń lub użyć skrótu klawiaturowego Ctrl+D.
Twój wiersz poleceń powinien teraz wrócić do stanu sprzed uruchomienia kontenera.
1.3.4. Zamontuj dane w kontenerze¶
Jak wspomniano wcześniej, kontener jest domyślnie odizolowany od systemu hosta.
Aby pozwolić kontenerowi na dostęp do systemu plików hosta, możesz zamontować wolumen z systemu hosta do kontenera, używając następującej składni:
W naszym przypadku <ścieżka_zewnętrzna> będzie bieżącym katalogiem roboczym, więc możemy po prostu użyć kropki (.), a <ścieżka_wewnętrzna> to alias, który wymyślamy; nazwijmy go /my_project (ścieżka wewnętrzna musi być bezwzględna).
Aby zamontować wolumen, zastępujemy ścieżki i dodajemy argument montowania wolumenu do polecenia docker run w następujący sposób:
docker run --rm -it -v .:/my_project 'community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273' /bin/bash
To montuje bieżący katalog roboczy jako wolumen, który będzie dostępny pod /my_project wewnątrz kontenera.
Możesz sprawdzić, czy to działa, wylistowując zawartość /my_project:
Wynik polecenia
Teraz możesz zobaczyć zawartość katalogu roboczego z wnętrza kontenera, w tym plik greetings.csv w katalogu data/.
To skutecznie utworzyło tunel przez ścianę kontenera, którego możesz użyć do dostępu do tej części systemu plików.
1.3.5. Użyj zamontowanych danych¶
Teraz, gdy zamontowaliśmy katalog roboczy w kontenerze, możemy użyć polecenia cowpy do wyświetlenia zawartości pliku greetings.csv.
W tym celu użyjemy cat /my_project/data/greetings.csv |, aby przekierować zawartość pliku CSV do polecenia cowpy.
Wynik polecenia
____________________
/ Hello,English,123 \
| Bonjour,French,456 |
\ Holà,Spanish,789 /
--------------------
\ ,+*^^*+___+++_
\ ,*^^^^ )
\ _+* ^**+_
\ +^ _ _++*+_+++_, )
_+^^*+_ ( ,+*^ ^ \+_ )
{ ) ( ,( ,_+--+--, ^) ^\
{ (\@) } f ,( ,+-^ __*_*_ ^^\_ ^\ )
{:;-/ (_+*-+^^^^^+*+*<_ _++_)_ ) ) /
( / ( ( ,___ ^*+_+* ) < < \
U _/ ) *--< ) ^\-----++__) ) ) )
( ) _(^)^^)) ) )\^^^^^))^*+/ / /
( / (_))_^)) ) ) ))^^^^^))^^^)__/ +^^
( ,/ (^))^)) ) ) ))^^^^^^^))^^) _)
*+__+* (_))^) ) ) ))^^^^^^))^^^^^)____*^
\ \_)^)_)) ))^^^^^^^^^^))^^^^)
(_ ^\__^^^^^^^^^^^^))^^^^^^^)
^\___ ^\__^^^^^^))^^^^^^^^)\\
^^^^^\uuu/^^\uuu/^^^^\^\^\^\^\^\^\^\
___) >____) >___ ^\_\_\_\_\_\_\)
^^^//\\_^^//\\_^ ^(\_\_\_\)
^^^ ^^ ^^^ ^
To produkuje pożądaną grafikę ASCII indyka recytującego nasze przykładowe pozdrowienia! Tyle że tutaj indyk powtarza pełne wiersze zamiast samych pozdrowień. Wiemy już, że nasz workflow Nextflow zrobi to lepiej!
Możesz poeksperymentować z tym poleceniem. Gdy skończysz, wyjdź z kontenera jak poprzednio:
Wrócisz do normalnej powłoki.
Podsumowanie¶
Wiesz już, jak pobrać kontener i uruchomić go jednorazowo lub interaktywnie. Wiesz również, jak udostępnić Swoje dane z wnętrza kontenera, co pozwala wypróbować każde interesujące Cię narzędzie na prawdziwych danych bez konieczności instalowania oprogramowania na Swoim systemie.
Co dalej?¶
Naucz się używać kontenerów do wykonywania procesów Nextflow.
2. Używaj kontenerów w Nextflow¶
Nextflow ma wbudowaną obsługę uruchamiania procesów wewnątrz kontenerów, co pozwala korzystać z narzędzi, których nie masz zainstalowanych w swoim środowisku obliczeniowym. Oznacza to, że możesz użyć dowolnego obrazu do wykonywania zadań, a Nextflow zajmie się pobieraniem obrazu, montowaniem danych i obsługą całego cyklu życia kontenera.
Aby to zademonstrować, dodamy krok cowpy do pipeline, który rozwijaliśmy, po kroku collectGreetings.
Zamuucz, jeśli jesteś gotowy!
2.1. Napisz moduł cowpy¶
Najpierw utwórzmy moduł procesu cowpy.
2.1.1. Utwórz plik dla nowego modułu¶
Utwórz pusty plik dla modułu o nazwie cowpy.nf.
To daje nam miejsce na umieszczenie kodu procesu.
2.1.2. Skopiuj kod procesu cowpy do pliku modułu¶
Możemy wzorować nasz proces cowpy na innych procesach, które napisaliśmy wcześniej.
| modules/cowpy.nf | |
|---|---|
Proces oczekuje input_file zawierającego pozdrowienia oraz wartości character.
Wyjściem będzie nowy plik tekstowy zawierający grafikę ASCII wygenerowaną przez narzędzie cowpy.
2.2. Dodaj cowpy do workflow¶
Teraz musimy zaimportować moduł i wywołać proces.
2.2.1. Importuj proces cowpy do hello-containers.nf¶
Wstaw deklarację importu powyżej bloku workflow i wypełnij ją odpowiednio.
Teraz moduł cowpy jest dostępny do użycia w workflow.
2.2.2. Dodaj wywołanie procesu cowpy w workflow¶
Połączmy proces cowpy() z wyjściem procesu collectGreetings(), który jak pamiętasz produkuje dwa wyjścia:
collectGreetings.out.outfilezawiera plik wyjściowy <--to, czego potrzebujemycollectGreetings.out.reportzawiera plik raportu z liczbą pozdrowień na partię
W bloku workflow wprowadź następującą zmianę w kodzie:
Zauważ, że zadeklarowaliśmy nowy parametr CLI, params.character, aby określić, która postać ma wypowiedzieć pozdrowienia.
2.2.3. Dodaj parametr character do bloku params¶
To technicznie jest opcjonalne, ale jest to zalecana praktyka i okazja do ustawienia domyślnej wartości dla postaci.
Teraz możemy być leniwi i pominąć wpisywanie parametru postaci w naszych poleceniach.
2.2.4. Zaktualizuj wyjścia workflow¶
Musimy zaktualizować wyjścia workflow, aby publikować wyjście procesu cowpy.
2.2.4.1. Zaktualizuj sekcję publish:¶
W bloku workflow wprowadź następującą zmianę w kodzie:
Proces cowpy produkuje tylko jedno wyjście, więc możemy się do niego odnieść w zwykły sposób, dodając .out.
Ale na razie dokończmy aktualizację wyjść na poziomie workflow.
2.2.4.2. Zaktualizuj blok output¶
Musimy dodać końcowe wyjście cowpy_art do bloku output. Przy okazji edytujmy również miejsca docelowe publikacji, ponieważ teraz nasz pipeline jest kompletny i wiemy, które wyjścia naprawdę nas interesują.
W bloku output wprowadź następujące zmiany w kodzie:
Teraz opublikowane wyjścia będą nieco lepiej zorganizowane.
2.2.5. Uruchom workflow¶
Podsumowując, oto co chcemy osiągnąć:
Myślisz, że zadziała?
Usuńmy poprzednie opublikowane wyjścia, aby mieć czystą kartę, i uruchommy workflow z flagą -resume.
Wynik polecenia (zredagowany dla przejrzystości)
N E X T F L O W ~ version 25.10.2
Launching `hello-containers.nf` [lonely_woese] DSL2 - revision: abf1dccf7f
executor > local (1)
[c9/f5c686] sayHello (3) [100%] 3 of 3, cached: 3 ✔
[ef/3135a8] convertToUpper (3) [100%] 3 of 3, cached: 3 ✔
[7f/f435e3] collectGreetings [100%] 1 of 1, cached: 1 ✔
[9b/02e776] cowpy [ 0%] 0 of 1 ✘
ERROR ~ Error executing process > 'cowpy'
Caused by:
Process `cowpy` terminated with an error exit status (127)
Command executed:
cat COLLECTED-batch-output.txt | cowpy -c "turkey" > cowpy-COLLECTED-batch-output.txt
Command exit status:
127
Command output:
(empty)
Command error:
.command.sh: line 2: cowpy: command not found
Work dir:
/workspaces/training/hello-nextflow/work/9b/02e7761db848f82db3c3e59ff3a9b6
Tip: when you have fixed the problem you can continue the execution adding the option `-resume` to the run command line
-- Check '.nextflow.log' file for details
ERROR ~ Cannot access first() element from an empty List
-- Check '.nextflow.log' file for details
O nie, jest błąd!
Kod błędu podany przez error exit status (127) oznacza, że żądany plik wykonywalny nie został znaleziony.
To ma sens, ponieważ wywołujemy narzędzie cowpy, ale tak naprawdę nie określiliśmy jeszcze kontenera (ups).
2.3. Użyj kontenera do uruchomienia procesu cowpy¶
Musimy określić kontener i powiedzieć Nextflow, aby użył go dla procesu cowpy().
2.3.1. Określ kontener dla cowpy¶
Możemy użyć tego samego obrazu, którego używaliśmy bezpośrednio w pierwszej sekcji tego samouczka.
Edytuj moduł cowpy.nf, aby dodać dyrektywę container do definicji procesu w następujący sposób:
| modules/cowpy.nf | |
|---|---|
To mówi Nextflow, że jeśli użycie Docker jest włączone, powinien użyć określonego tutaj obrazu kontenera do wykonania procesu.
2.3.2. Włącz użycie Docker przez plik nextflow.config¶
Zauważ, że wspomnieliśmy 'jeśli użycie Docker jest włączone'. Domyślnie nie jest, więc musimy włączyć tę opcję w Nextflow. W tym celu nieco uprzedzamy temat następnej i ostatniej części tego kursu (Część 6), która obejmuje konfigurację.
Jednym z głównych sposobów konfigurowania wykonywania workflow, które oferuje Nextflow, jest użycie pliku nextflow.config.
Gdy taki plik jest obecny w bieżącym katalogu, Nextflow automatycznie go załaduje i zastosuje zawartą w nim konfigurację.
Dostarczyliśmy plik nextflow.config z jedną linią kodu, która jawnie wyłącza Docker: docker.enabled = false.
Teraz zmieńmy to na true, aby włączyć Docker:
Wskazówka
Możliwe jest włączenie wykonywania Docker z wiersza poleceń, dla pojedynczego uruchomienia, używając parametru -with-docker <kontener>.
Jednak pozwala to tylko na określenie jednego kontenera dla całego workflow, podczas gdy podejście, które właśnie pokazaliśmy, pozwala na określenie innego kontenera dla każdego procesu.
To jest lepsze dla modularności, utrzymania kodu i powtarzalności.
2.3.3. Uruchom workflow z włączonym Docker¶
Uruchom workflow z flagą -resume:
Wynik polecenia
N E X T F L O W ~ version 25.10.2
Launching `hello-containers.nf` [drunk_perlman] DSL2 - revision: abf1dccf7f
executor > local (1)
[c9/f5c686] sayHello (3) [100%] 3 of 3, cached: 3 ✔
[ef/3135a8] convertToUpper (3) [100%] 3 of 3, cached: 3 ✔
[7f/f435e3] collectGreetings [100%] 1 of 1, cached: 1 ✔
[98/656c6c] cowpy [100%] 1 of 1 ✔
Tym razem rzeczywiście działa! Jak zwykle wyjścia workflow znajdziesz w odpowiednim katalogu results, choć tym razem są nieco lepiej zorganizowane, z tylko raportem i końcowym wyjściem na najwyższym poziomie, a wszystkie pliki pośrednie schowane w podkatalogu.
Zawartość katalogu
Końcowa grafika ASCII znajduje się w katalogu results/hello_containers/, pod nazwą cowpy-COLLECTED-batch-output.txt.
Zawartość pliku
_________
/ HOLà \
| HELLO |
\ BONJOUR /
---------
\ ,+*^^*+___+++_
\ ,*^^^^ )
\ _+* ^**+_
\ +^ _ _++*+_+++_, )
_+^^*+_ ( ,+*^ ^ \+_ )
{ ) ( ,( ,_+--+--, ^) ^\
{ (\@) } f ,( ,+-^ __*_*_ ^^\_ ^\ )
{:;-/ (_+*-+^^^^^+*+*<_ _++_)_ ) ) /
( / ( ( ,___ ^*+_+* ) < < \
U _/ ) *--< ) ^\-----++__) ) ) )
( ) _(^)^^)) ) )\^^^^^))^*+/ / /
( / (_))_^)) ) ) ))^^^^^))^^^)__/ +^^
( ,/ (^))^)) ) ) ))^^^^^^^))^^) _)
*+__+* (_))^) ) ) ))^^^^^^))^^^^^)____*^
\ \_)^)_)) ))^^^^^^^^^^))^^^^)
(_ ^\__^^^^^^^^^^^^))^^^^^^^)
^\___ ^\__^^^^^^))^^^^^^^^)\\
^^^^^\uuu/^^\uuu/^^^^\^\^\^\^\^\^\^\
___) >____) >___ ^\_\_\_\_\_\_\)
^^^//\\_^^//\\_^ ^(\_\_\_\)
^^^ ^^ ^^^ ^
I oto jest, nasz piękny indyk wypowiadający pozdrowienia zgodnie z oczekiwaniami.
2.3.4. Sprawdź, jak Nextflow uruchomił skonteneryzowane zadanie¶
Na zakończenie tej sekcji przyjrzyjmy się podkatalogowi work dla jednego z wywołań procesu cowpy, aby uzyskać trochę więcej wglądu w to, jak Nextflow pracuje z kontenerami pod maską.
Sprawdź wynik polecenia nextflow run, aby znaleźć ścieżkę do podkatalogu work dla procesu cowpy.
Patrząc na to, co otrzymaliśmy dla pokazanego powyżej uruchomienia, linia logu konsoli dla procesu cowpy zaczyna się od [98/656c6c].
Odpowiada to następującej skróconej ścieżce katalogu: work/98/656c6c.
W tym katalogu znajdziesz plik .command.run, który zawiera wszystkie polecenia, które Nextflow uruchomił w Twoim imieniu podczas wykonywania pipeline.
Zawartość pliku
#!/bin/bash
### ---
### name: 'cowpy'
### container: 'community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273'
### outputs:
### - 'cowpy-COLLECTED-batch-output.txt'
### ...
set -e
set -u
NXF_DEBUG=${NXF_DEBUG:=0}; [[ $NXF_DEBUG > 1 ]] && set -x
NXF_ENTRY=${1:-nxf_main}
nxf_sleep() {
sleep $1 2>/dev/null || sleep 1;
}
nxf_date() {
local ts=$(date +%s%3N);
if [[ ${#ts} == 10 ]]; then echo ${ts}000
elif [[ $ts == *%3N ]]; then echo ${ts/\%3N/000}
elif [[ $ts == *3N ]]; then echo ${ts/3N/000}
elif [[ ${#ts} == 13 ]]; then echo $ts
else echo "Unexpected timestamp value: $ts"; exit 1
fi
}
nxf_env() {
echo '============= task environment ============='
env | sort | sed "s/\(.*\)AWS\(.*\)=\(.\{6\}\).*/\1AWS\2=\3xxxxxxxxxxxxx/"
echo '============= task output =================='
}
nxf_kill() {
declare -a children
while read P PP;do
children[$PP]+=" $P"
done < <(ps -e -o pid= -o ppid=)
kill_all() {
[[ $1 != $$ ]] && kill $1 2>/dev/null || true
for i in ${children[$1]:=}; do kill_all $i; done
}
kill_all $1
}
nxf_mktemp() {
local base=${1:-/tmp}
mkdir -p "$base"
if [[ $(uname) = Darwin ]]; then mktemp -d $base/nxf.XXXXXXXXXX
else TMPDIR="$base" mktemp -d -t nxf.XXXXXXXXXX
fi
}
nxf_fs_copy() {
local source=$1
local target=$2
local basedir=$(dirname $1)
mkdir -p $target/$basedir
cp -fRL $source $target/$basedir
}
nxf_fs_move() {
local source=$1
local target=$2
local basedir=$(dirname $1)
mkdir -p $target/$basedir
mv -f $source $target/$basedir
}
nxf_fs_rsync() {
rsync -rRl $1 $2
}
nxf_fs_rclone() {
rclone copyto $1 $2/$1
}
nxf_fs_fcp() {
fcp $1 $2/$1
}
on_exit() {
local last_err=$?
local exit_status=${nxf_main_ret:=0}
[[ ${exit_status} -eq 0 && ${nxf_unstage_ret:=0} -ne 0 ]] && exit_status=${nxf_unstage_ret:=0}
[[ ${exit_status} -eq 0 && ${last_err} -ne 0 ]] && exit_status=${last_err}
printf -- $exit_status > /workspaces/training/hello-nextflow/work/98/656c6c90cce1667c094d880f4b6dcc/.exitcode
set +u
docker rm $NXF_BOXID &>/dev/null || true
exit $exit_status
}
on_term() {
set +e
docker stop $NXF_BOXID
}
nxf_launch() {
docker run -i --cpu-shares 1024 -e "NXF_TASK_WORKDIR" -v /workspaces/training/hello-nextflow/work:/workspaces/training/hello-nextflow/work -w "$NXF_TASK_WORKDIR" --name $NXF_BOXID community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273 /bin/bash -ue /workspaces/training/hello-nextflow/work/98/656c6c90cce1667c094d880f4b6dcc/.command.sh
}
nxf_stage() {
true
# stage input files
rm -f COLLECTED-batch-output.txt
ln -s /workspaces/training/hello-nextflow/work/7f/f435e3f2cf95979b5f3d7647ae6696/COLLECTED-batch-output.txt COLLECTED-batch-output.txt
}
nxf_unstage_outputs() {
true
}
nxf_unstage_controls() {
true
}
nxf_unstage() {
if [[ ${nxf_main_ret:=0} == 0 ]]; then
(set -e -o pipefail; (nxf_unstage_outputs | tee -a .command.out) 3>&1 1>&2 2>&3 | tee -a .command.err)
nxf_unstage_ret=$?
fi
nxf_unstage_controls
}
nxf_main() {
trap on_exit EXIT
trap on_term TERM INT USR2
trap '' USR1
[[ "${NXF_CHDIR:-}" ]] && cd "$NXF_CHDIR"
export NXF_BOXID="nxf-$(dd bs=18 count=1 if=/dev/urandom 2>/dev/null | base64 | tr +/ 0A | tr -d '\r\n')"
NXF_SCRATCH=''
[[ $NXF_DEBUG > 0 ]] && nxf_env
touch /workspaces/training/hello-nextflow/work/98/656c6c90cce1667c094d880f4b6dcc/.command.begin
set +u
set -u
[[ $NXF_SCRATCH ]] && cd $NXF_SCRATCH
export NXF_TASK_WORKDIR="$PWD"
nxf_stage
set +e
(set -o pipefail; (nxf_launch | tee .command.out) 3>&1 1>&2 2>&3 | tee .command.err) &
pid=$!
wait $pid || nxf_main_ret=$?
nxf_unstage
}
$NXF_ENTRY
Jeśli wyszukasz nxf_launch w tym pliku, powinieneś zobaczyć coś takiego:
nxf_launch() {
docker run -i --cpu-shares 1024 -e "NXF_TASK_WORKDIR" -v /workspaces/training/hello-nextflow/work:/workspaces/training/hello-nextflow/work -w "$NXF_TASK_WORKDIR" --name $NXF_BOXID community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273 /bin/bash -ue /workspaces/training/hello-nextflow/work/98/656c6c90cce1667c094d880f4b6dcc/.command.sh
}
Jak widać, Nextflow używa polecenia docker run do uruchomienia wywołania procesu.
Montuje również odpowiedni podkatalog work do kontenera, ustawia odpowiednio katalog roboczy wewnątrz kontenera i uruchamia nasz szablonowy skrypt bash w pliku .command.sh.
Cała ciężka praca, którą musieliśmy wykonać ręcznie w pierwszej sekcji? Nextflow robi to za nas za kulisami!
_______________________
< Hurray for robots...! >
-----------------------
,-----.
| |
,--| |-.
__,----| | | |
,;:: | `_____' |
`._______| i^i |
`----| |---'| .
,-------._| |== ||//
| |_|P`. /'/
`-------' 'Y Y/'/'
.==\ /_\
^__^ / /'| `i
(oo)\_______ /' / | |
(__)\ )\/\ /' / | `i
||----w | ___,;`----'.___L_,-'`\__
|| || i_____;----\.____i""\____\
Podsumowanie¶
Wiesz już, jak używać kontenerów w Nextflow do uruchamiania procesów.
Co dalej?¶
Zrób przerwę!
Gdy będziesz gotowy, przejdź do Część 6: Hello Config, aby dowiedzieć się, jak konfigurować wykonywanie pipeline, aby dopasować go do Twojej infrastruktury, a także zarządzać konfiguracją wejść i parametrów.
To ostatnia część i potem ukończysz ten kurs!
Quiz¶
Czym jest kontener?
Jaka jest różnica między obrazem kontenera a instancją kontenera?
Co robi flaga -v w poleceniu docker run?
Dlaczego trzeba montować wolumeny podczas używania kontenerów?
Jak określasz kontener dla procesu Nextflow?
Które ustawienie nextflow.config włącza Docker dla Twojego workflow?
Co Nextflow automatycznie obsługuje podczas uruchamiania procesu w kontenerze? (Wybierz wszystkie pasujące)