====== Docker Advanced ======
===== Dockerfiles =====
==== ARGS ====
Con el comando ARGS puedes definir, dentro del Dockerfile, qué argumentos se pueden usar para construir una imagen:
ARG [=]
En el siguiente ejemplo se añade un argumento sin valor por defecto ''user'', uno con valor por defecto ''3'' y luego se usa el argumento con la sintaxis ''$user''.
FROM busybox
ARG user
ARG buildno=3
USER $user
===== Images =====
==== Contexto ====
Como ya sabes el siguiente comando construirá una imagen a partir del Docker file en el directorio actual y la taggeará como ''automatron''. Aún así el ''.'' del final no es dónde la genera sino cual es el contexto (el parámetro para indicar el Dockerfile es ''-f''):
docker build -t automatron .
Docker no puede salirse de su contexto para buscar ficheros a la hora de construir una imagen.
==== Save and load a physical image ====
docker save --output ../dist/puma-app-docker.tar gtd/puma_app:$VERSION
docker load --input puma-app-docker.tar
===== Networks =====
===== Volumenes =====
$ docker volume create portainer_data
$ docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
Listar, eliminar... volumenes
$ docker volume ls
$ docker volume rm
==== Copiar un fichero a un volumen ====
Imaginemos que queremos copiar un fichero a un volúmen que está siendo usado por un contenedor (y luego darle permisos y ejecutar una acción concreta):
$ docker cp file_backup.tar :/var/opt/gitlab/backups
$ docker exec chown git:root /var/opt/gitlab/backups/COMA-CORE1-dataset_gitlab_backup.tar
$ docker exec -it fa38 gitlab-rake gitlab:backup:restore
Siempre necesitaremos un contenedor corriendo para copiar el fichero, tenemos las siguientes opciones:
docker container create --name dummy -v myvolume:/root hello-world
docker cp c:\myfolder\myfile.txt dummy:/root/myfile.txt
docker rm dummy
En una línea:
docker run --rm -v $PWD:/source -v my_volume:/dest -w /source alpine cp myfile.txt /dest
O incluso en un contenedor creado desde cero con un Dockerfile con:
FROM scratch
CMD
Luego:
docker build -t nothing .
docker container create --name dummy -v myvolume:/root nothing
docker cp c:\myfolder\myfile.txt dummy:/root/myfile.txt
docker rm dummy
==== Creación de un volumen mapeado en nfs (docker-compose) ====
volumes:
nas-owncloud:
driver: local
driver_opts:
type: nfs
o: "addr=10.10.10.10,nolock,soft,rw"
device: ":/volume1/sir-vices/owncloud"
services:
owncloud:
volumes:
- nas-owncloud:/mnt/data
===== Compose =====
==== Environment variables ====
It’s possible to use environment variables in your shell to populate values inside a Compose file:
web:
image: "webapp:${TAG}"
You can set environment variables with the ''environment'' key, just like with ''docker run -e VARIABLE=VALUE ...'':
web:
environment:
- DEBUG=1
Pass environment variables to containers without giving a value:
web:
environment:
- DEBUG
You can pass multiple environment variables from an external file with the ''env_file'' option, just like with ''docker run --env-file=FILE ...'':
web:
env_file:
- web-variables.env
Just like with ''docker run -e'', you can set environment variables with ''docker-compose run -e'':
docker-compose run -e DEBUG=1 web python console.py
You can also pass a variable through from the shell by not giving it a value:
docker-compose run -e DEBUG web python console.py
You can set default values for any environment variables referenced in the Compose file, or used to configure Compose, in an environment file named .env:
$ cat .env
TAG=v1.5
$ cat docker-compose.yml
version: '3'
services:
web:
image: "webapp:${TAG}"
===== Execute GUI programs =====
You can create a Dockerfile where you install a Firefox, a Visual Studio Code... Whatever. Then, as the X11 Linux programs work like client\server you only need to bind the socket. \\
For example, a Dockerfile could be this:
FROM ubuntu:14.04
RUN apt-get update && apt-get install -y firefox
RUN export uid=1000 gid=1000 && \
mkdir -p /home/developer && \
echo "developer:x:${uid}:${gid}:Developer,,,:/home/developer:/bin/bash" >> /etc/passwd && \
echo "developer:x:${uid}:" >> /etc/group && \
echo "developer ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/developer && \
chmod 0440 /etc/sudoers.d/developer && \
chown ${uid}:${gid} -R /home/developer
USER developer
ENV HOME /home/developer
CMD /usr/bin/firefox
Then you only need to buid it:
docker build -t firefox .
And launch it using your x11 socket:
docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
firefox
You could also use the run with the cmd as parameter, in this way you could install several programs and launch them with this.
==== Launch them from SSH ====
As it says here [[https://docs.docker.com/engine/examples/running_ssh_service/]] you can create a Dockerfile with...
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:THEPASSWORDYOUCREATED' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
... for an ssh server.
This one will be prepared for launching a remote firefox in your local machine if you connect to it via ssh and launch it.
FROM ubuntu:14.04
RUN apt-get update && apt-get install -y firefox openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:train' | chpasswd
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
RUN echo "X11UseLocalhost no" >> /etc/ssh/sshd_config
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
# CMD tail -f /dev/null