2. Docker

2.11. Integrar dades al contenidor Docker

Moltes vegades necessitarem utilitzar un input de manera sistemàtica en un contenidor. Per exemple, si volem fer una variant call utilitzant GATK, els genomes de referència sempre seran els mateixos i, tal vegada, és interessant guardar-los dins del contenidor per assegurar-nos la reproductibilitat dels resultats per tal que no depengui de la referència utilitzada. Per a un cas més simple introduirem el nostre script num.py al contenidor. Per això crearem una nova imatge modificant el Dockerfile.

Hi afegirem una nova línia:

COPY num.py /home

Estarem fent una còpia de l’script al home del contenidor. Fem una altra imatge:

$ docker image build -t uoc/alpine-num .

Si ara entrem de forma interactiva dins del contenidor i llistem els arxius dins el home, trobarem l’arxiu num.py:

$ docker container run --rm -it uoc/alpine-num sh

És important com ordenem les ordres al Dockerfile. És recomanable fer les ordres COPY després dels RUN, ja que, quan fem el build, Docker va per ordre i, si en algun moment volem afegir un altre script en lloc de num.py, si el COPY es troba al final del procés, Docker utilitzarà els RUN que té a la memòria no haurà de construir la imatge de zero, i el procés serà molt més ràpid. Docker va línia a línia i, si aquesta capa o conjunt de capes ja la té en memòria caché, agilitza el procés perquè no ha de reinstal·lar-les.

Si les dades que volem introduir en la nostra imatge són a internet, podem copiar-les directament fent servir RUN. Podríem afegir aquestes línies al Dockerfile com a exemple:

RUN wget https://ftp.ncbi.nlm.nih.gov/refseq/H_sapiens/annotation/GRCh38_latest/refseq_identifiers/GRCh38_latest_clinvar.vcf.gz

Per defecte, l’arxiu es copia en el root del sistema del contenidor. Si el volguéssim moure a una altra localització, podríem especificar-la:

RUN mv GRCh38_latest_clinvar.vcf.gz /home

… i la copiaria a la nostra carpeta /home.

Ara que sabem com introduir l’script dins del contenidor, podem crear un nou contenidor que corri l’script automàticament. Hem de substituir CMD del Dockerfile a:

CMD ["python3","/home/num.py"]

D’aquesta manera creem una nova imatge:

$ docker image build -t uoc/alpine-numpy-ex .

… i executem directament:

$ docker container run --rm uoc/alpine-numpy-ex

… i ens retorna el resultat de l’arxiu num.py.

Si volem introduir un nou script de Python (atcg.py) on el seu resultat depengui d’un argument:

import sys

filename = sys.argv[1]

filenumb = len(filename)

print (filenumb)

… i el copiarem mitjançant Dockerfile:

COPY atcg.py /home

… i crearem una nova imatge:

$ docker image build -t uoc/alpine-atcg .
Si el fem córrer directament, tindrem el resultat del CMD (en el nostre cas, la versió de Python); mentre que, si afegim arguments a l’ordre run, se sobreescriu CMD i obtenim el resultat del nou script:
$ docker container run --rm uoc/alpine-atcg python3 /home/atcg.py ATG

Si volguéssim tenir aquest nou script com ordres per defecte, al Dockerfile hauríem de canviar la línia de CMD pels valors per defecte i crear una nova línia anomenada ENTRYPOINT per localitzar l’script:

ENTRYPOINT ["python3","atcg.py"]

CMD ["ACTG"]

També podem afegir abans de ENTRYPOINT i CMD una entrada per definir el directori de treball:

WORKDIR /home

D’aquesta manera, si creem una nova imatge uoc/alpine-entry i executem el contenidor directament:

$ docker container run  --rm uoc/alpine-entry

Ens retornarà «4», la longitud de la línia «ACTG» ubicada per defecte al Dockerfile. Si ara, al final de l’ordre run, hi afegim un altre input, aquest substituirà el de CMD:

$ docker container run  --rm uoc/alpine-entry Genetica

Retornarà «8».

Podem observar la relació entre ENTRYPOINT i CMD en la següent taula.

Taula 5.

No ENTRYPOINT ENTRYPOINT exec_entry p1_entry ENTRYPOINT [“exec_entry”, “p1_entry”]
No CMD error, not allowed /bin/sh -c exec_entry p1_entry exec_entry p1_entry
CMD [“exec_cmd”, “p1_cmd”] exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry exec_cmd p1_cmd
CMD exec_cmd p1_cmd /bin/sh -c exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

Font: elaboració pròpia.