{"id":146,"date":"2023-09-01T14:04:49","date_gmt":"2023-09-01T12:04:49","guid":{"rendered":"http:\/\/eines-informatiques.recursos.uoc.edu\/entornos-y-contenedores\/?page_id=146"},"modified":"2025-03-09T13:28:09","modified_gmt":"2025-03-09T11:28:09","slug":"2-11-integrar-datos-en-el-contenedor-docker","status":"publish","type":"page","link":"http:\/\/eines-informatiques.recursos.uoc.edu\/entornos-y-contenedores\/es\/2-11-integrar-datos-en-el-contenedor-docker\/","title":{"rendered":"2.11. Integrar datos en el contenedor Docker"},"content":{"rendered":"<p>Muchas veces necesitaremos utilizar un <em>input <\/em>de manera sistem\u00e1tica en un contenedor. Por ejemplo, si queremos hacer un <em>variant call<\/em> utilizando GATK, los genomas de referencia siempre ser\u00e1n los mismos y tal vez es interesante guardarlos dentro del contenedor para asegurarnos la reproducibilidad de los resultados a fin de que no dependa de la referencia utilizada. Para un caso m\u00e1s simple introduciremos nuestro <em>script num.py<\/em> en el contenedor. Para ello crearemos una nueva imagen modificando el Dockerfile.<\/p>\n<p>A\u00f1adiremos una nueva l\u00ednea:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">COPY num.py \/home<\/pre>\n<p>Estaremos haciendo una copia del <em>script <\/em>en el home del contenedor. Hacemos otra imagen:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"mowtwo\">$ docker image build -t uoc\/alpine-num .<\/pre>\n<p>Si ahora entramos de forma interactiva dentro del contenedor y list\u00e1is los archivos dentro de \/home encontrareis el archivo <em>num.py<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"mowtwo\">$ docker container run --rm -it uoc\/alpine-num sh<\/pre>\n<p>El orden de los comandos en el Dockerfile es importante. Es recomendable hacer los comandos COPY despu\u00e9s de los RUN, ya que al hacer el <em>build<\/em>, Docker va por orden, y si en alg\u00fan momento queremos a\u00f1adir otro <em>script<\/em> en lugar de <em>num.py<\/em>, si el COPY est\u00e1 al final del proceso, Docker utiliza los RUNs que tiene en memoria y no ha de construir la imagen de cero, y el proceso es mucho m\u00e1s r\u00e1pido. Docker va l\u00ednea a l\u00ednea, y si esa capa o conjunto de capas ya la tiene en memoria <em>cach\u00e9<\/em> agiliza el proceso no reinstal\u00e1ndolas.<\/p>\n<p>Si los datos que queremos introducir dentro de nuestra imagen est\u00e1n en internet, directamente podemos copiarlos utilizando RUN. Podr\u00edamos a\u00f1adir estas l\u00edneas en el Dockerfile como ejemplo:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">RUN wget https:\/\/ftp.ncbi.nlm.nih.gov\/refseq\/H_sapiens\/annotation\/GRCh38_latest\/refseq_identifiers\/GRCh38_latest_clinvar.vcf.gz<\/pre>\n<p>Por defecto, el archivo se copia en el <em>root<\/em> del sistema del contenedor. Si quisi\u00e9ramos moverlo a otra localizaci\u00f3n podr\u00edamos especificarla:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">RUN mv GRCh38_latest_clinvar.vcf.gz \/home<\/pre>\n<p>y la copiar\u00eda en nuestra carpeta \/home.<\/p>\n<p>Ahora que sabemos c\u00f3mo introducir el <em>script <\/em>dentro del contenedor, podemos crear un nuevo contenedor que corra el <em>script<\/em> autom\u00e1ticamente. Debemos substituir CMD del Dockerfile a:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">CMD [\"python3\",\"\/home\/num.py\"]<\/pre>\n<p>De esta manera creamos una nueva imagen:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"mowtwo\">$ docker image build -t uoc\/alpine-numpy-ex .<\/pre>\n<p>y ejecutamos directamente:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"mowtwo\">$ docker container run --rm uoc\/alpine-numpy-ex<\/pre>\n<p>y nos devuelve el resultado del archivo <em>num.py<\/em>.<\/p>\n<p>Si queremos introducir un nuevo <em>script<\/em> de Python (<em>atcg.py<\/em>) donde su resultado dependa de un argumento,<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">import sys\r\n\r\nfilename = sys.argv[1]\r\n\r\nfilenumb = len(filename)\r\n\r\nprint (filenumb)<\/pre>\n<p>lo copiaremos mediante Dockerfile:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">COPY atcg.py \/home<\/pre>\n<p>y crearemos una nueva imagen:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"mowtwo\">$ docker image build -t uoc\/alpine-atcg .<\/pre>\n<p>Si lo corremos directamente, tendremos el resultado del CMD (en nuestro caso, la versi\u00f3n de Python); mientras que si a\u00f1adimos argumentos al comando <code>run<\/code>, sobrescribe CMD y obtenemos el resultado del nuevo <em>script<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"mowtwo\">$ docker container run --rm uoc\/alpine-atcg python3 \/home\/atcg.py ATG<\/pre>\n<p>Si quisi\u00e9ramos tener este nuevo <em>script<\/em> como los comandos por defecto deber\u00edamos cambiar en el Dockerfile la l\u00ednea de CMD por los valores por defecto y crear una nueva l\u00ednea nombrada ENTRYPOINT para localizar el <em>script<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">ENTRYPOINT [\"python3\",\"atcg.py\"]\r\n\r\nCMD [\"ACTG\"]<\/pre>\n<p>Tambi\u00e9n podemos a\u00f1adir antes que ENTRYPOINT y CMD una entrada para definir el directorio de trabajo:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">WORKDIR \/home<\/pre>\n<p>De esta manera, si creamos una nueva imagen <code>uoc\/alpine-entry<\/code> y ejecutamos el contenedor directamente,<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"mowtwo\">$ docker container run\u00a0 --rm uoc\/alpine-entry<\/pre>\n<p>nos devolver\u00e1 \u00ab4\u00bb la longitud de la l\u00ednea \u00abACTG\u00bb ubicada por defecto en el Dockerfile. Si ahora al final del comando <code>run<\/code> a\u00f1adimos otro <em>input<\/em>, este sustituir\u00e1 al de CMD:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"mowtwo\">$ docker container run\u00a0 --rm uoc\/alpine-entry Genetica<\/pre>\n<p>Devolver\u00e1 \u00ab8\u00bb.<\/p>\n<p>La relaci\u00f3n entre ENTRYPOINT y CMD la podemos observar en la siguiente tabla.<\/p>\n<div class=\"tabletitle\"><p>Tabla 5.<\/p>\n<\/div>\n<table width=\"642\">\n<tbody>\n<tr>\n<td width=\"160\"><\/td>\n<td width=\"161\"><strong>No ENTRYPOINT<\/strong><\/td>\n<td width=\"161\"><strong>ENTRYPOINT<\/strong> exec_entry p1_entry<\/td>\n<td width=\"160\"><strong>ENTRYPOINT<\/strong> [\u00abexec_entry\u00bb, \u00abp1_entry\u00bb]<\/td>\n<\/tr>\n<tr>\n<td width=\"160\"><strong>No CMD<\/strong><\/td>\n<td width=\"161\">error, not allowed<\/td>\n<td width=\"161\">\/bin\/sh -c exec_entry p1_entry<\/td>\n<td width=\"160\">exec_entry p1_entry<\/td>\n<\/tr>\n<tr>\n<td width=\"160\"><strong>CMD<\/strong> [\u00abexec_cmd\u00bb, \u00abp1_cmd\u00bb]<\/td>\n<td width=\"161\">exec_cmd p1_cmd<\/td>\n<td width=\"161\">\/bin\/sh -c exec_entry p1_entry<\/td>\n<td width=\"160\">exec_entry p1_entry exec_cmd p1_cmd<\/td>\n<\/tr>\n<tr>\n<td width=\"160\"><strong>CMD<\/strong> exec_cmd p1_cmd<\/td>\n<td width=\"161\">\/bin\/sh -c exec_cmd p1_cmd<\/td>\n<td width=\"161\">\/bin\/sh -c exec_entry p1_entry<\/td>\n<td width=\"160\">exec_entry p1_entry \/bin\/sh -c exec_cmd p1_cmd<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"tablefooter\"><p>Fuente: elaboraci\u00f3n propia.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Muchas veces necesitaremos utilizar un input de manera sistem\u00e1tica en un contenedor. Por ejemplo, si queremos hacer un variant call utilizando GATK, los genomas de referencia siempre ser\u00e1n los mismos y tal vez es interesante guardarlos dentro del contenedor para asegurarnos la reproducibilidad de los resultados a fin de que no dependa de la referencia [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":[],"acf":[],"_links":{"self":[{"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/entornos-y-contenedores\/es\/wp-json\/wp\/v2\/pages\/146"}],"collection":[{"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/entornos-y-contenedores\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/entornos-y-contenedores\/es\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/entornos-y-contenedores\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/entornos-y-contenedores\/es\/wp-json\/wp\/v2\/comments?post=146"}],"version-history":[{"count":7,"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/entornos-y-contenedores\/es\/wp-json\/wp\/v2\/pages\/146\/revisions"}],"predecessor-version":[{"id":475,"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/entornos-y-contenedores\/es\/wp-json\/wp\/v2\/pages\/146\/revisions\/475"}],"wp:attachment":[{"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/entornos-y-contenedores\/es\/wp-json\/wp\/v2\/media?parent=146"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}