====== Instalacion Debian ====== fuente: https://docs.docker.com/engine/installation/linux/debian Cambiar directorio donde se instalan las imagenes: https://forums.docker.com/t/how-do-i-change-the-docker-image-installation-directory/1169 ====== Configuraciones ====== La forma recomendada de cambiar configuraciones por defecto es crear el archivo: sudo vim /etc/docker/daemon.json ===== Cambiar rango IP de los contenedores ===== 1. Editar: sudo vim /etc/docker/daemon.json Y añadir: { "bip": "10.59.0.1/16" } 2. Reiniciar el servicio: sudo service docker restart ===== Habilitar debug ===== https://success.docker.com/article/how-do-i-enable-debug-logging-of-the-docker-daemon 1. Editar: sudo vim /etc/docker/daemon.json Y añadir: { "debug": true } 2. Recargar el servicio: sudo kill -SIGHUP $(pidof dockerd) 3. Ver logs sudo tail -F /var/log/daemon.log ====== Ejecutar como no root ====== Para que el usuario "usuario" puede ejecutar docker sin sudo: 1. Añadirle al grupo "docker" sudo usermod -a -G docker usuario 2. Cerrar sesión bash. Quizá lo más drástico es cerrar window manager (Gnome, Awesome, etc...) ====== Crear imagenes ====== ===== Modificar tamaño de la imagen base ===== Por defecto la imagen es de 10Gb. Lo podemos ver haciendo: # docker info Base Device Size: 10 GB Para aumentarlo, paramos docker y lo arrancamos con el siguiente parámetro: # service docker stop Cambiamos /lib/systemd/system/docker.service ExecStart=/usr/bin/docker daemon --storage-opt dm.basesize=20G -H fd:// Actualizamos servicio por systemd: systemctl daemon-reload Ahora ya está a 20Gb: # docker info Base Device Size: 21.47 GB ===== Actualizar imagen previa ===== 1. Arrancar contenedor docker run -t -i training/sinatra /bin/bash 2. Hacer algun cambio gem install json 3. Hacer commit docker commit -m "Added json gem" -a "Kate Smith" \ 0b2616b0e5a8 ouruser/sinatra:v2 ===== Desde arhivo de config ===== 1. Crear archivo mkdir sinatra cd sinatra vim Dockerfile 2. Con el siguiente contenido: # This is a comment FROM ubuntu:14.04 MAINTAINER Kate Smith RUN apt-get update && apt-get install -y ruby ruby-dev RUN gem install sinatra 3. Generar la imagen. El parámetro -t es el nombre y el tag que le ponemos. El . es porque estamos en el directorio, indica la ruta al fichero Dockerfile docker build . -t ouruser/sinatra:v2 En un directorio diferente: docker build /sinatra -t ouruser/sinatra:v2 Y si tenemos otro nombre de fichero: docker build -f DockerfilePrueba . -t ouruser/sinatra:v2 ====== Entrar en un container como root ====== Si tenemos cambiado el usuario con el que se ejecuta docker podemos entrar como root de esta manera y luego cambiar la contraseña si nos conviene: docker exec -u 0 -it mycontainer bash docker exec -u root -it mycontainer bash ====== Cambiar politica de reinicio de contenedor ====== https://docs.docker.com/config/containers/start-containers-automatically/ Miramos que política tiene: docker inspect container_name| jq -r '.[0].HostConfig.RestartPolicy' { "Name": "always", "MaximumRetryCount": 0 } ^Flag^Description^ |no|Do not automatically restart the container. (the default)| |on-failure|Restart the container if it exits due to an error, which manifests as a non-zero exit code.| |always|Always restart the container if it stops. If it is manually stopped, it is restarted only when Docker daemon restarts or the container itself is manually restarted. (See the second bullet listed in restart policy details)| |unless-stopped|Similar to always, except that when the container is stopped (manually or otherwise), it is not restarted even after Docker daemon restarts.| Para cambiarlo docker update --restart unless-stopped container_name ====== Red ====== Hay 2 cambios importantes que se estan produciendo ahora mismo (ENE/2016): * Network. Caracteristica soportada por la version 1.9. Dejara obsoleta la opcion "--link" * IPs estaticas para contenedores. Esta previsto introducirla en la version 1.10, prevista para febrero de 2016 Hay un excelente artículo que las explica: https://docs.docker.com/network/network-tutorial-standalone/#use-the-default-bridge-network ===== Visibilidad contenedor_a <-> contenedor_b ===== La opción "--link" debe evitarse, está en desuso. Hay que resolver dos cuestiones: 1. Que haya conectividad a nivel de red entre contenedores 2. Que cada contenedor pueda acceder por nombre al otro contenedor. **IMPORTANTE**: la gracia es que si se destruye un contenedor y se vuelve a crear, se pueda detener y arrancar el otro contenedor. Con "--link" si se destruye el contenedor "enlazado", al detener el contenedor que lo referenciaba e intentar arrancarlo de nuevo NO podremos. ==== Sin docker compose ==== En este ejemplo: * Tenemos 3 contenedores 3, "sever_a", "server_b" y "server_c" * server_a y server_b tienen conectividad * Desde server_a se puede llegar a server_b por nombre * Desde server_b se puede llegar a server_a por nombre * Si se destruye server_b, se vuelve a crear y se detiene server_a, se podrá volver a arrancar server_a * server_c no llega a nivel de red (ni resuelve el nombre) de server_a ni de server_b 1. Crear la red docker network create network-private 2. Creamos los 3 contenedores 3 docker run --name server_a \ -ti \ --network network-private \ --net-alias server_a \ -d debian docker run --name server_b \ -ti \ --network network-private \ --net-alias server_b \ -d debian docker run --name server_c \ -ti \ -d debian 3. Desde "server_a" llegamos a "server_b" por nombre: 3.1. Nos conectamos docker exec -ti server_a bash 3.2. Ejecutamos: ping server_b Resultado esperado similar a: PING server_b (192.168.224.3) 56(84) bytes of data. 64 bytes from server_b.network-private (192.168.224.3): icmp_seq=1 ttl=64 time=0.222 ms 64 bytes from server_b.network-private (192.168.224.3): icmp_seq=2 ttl=64 time=0.134 ms ^C --- server_b ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1013ms rtt min/avg/max/mdev = 0.134/0.178/0.222/0.044 ms root@34e909656151:/# 3.3. Salimos exit 4. Re-creamos "server_b" docker stop server_b && docker rm server_b docker run --name server_b \ -ti \ --network network-private \ --net-alias server_b \ -d debian 5. Detenemos y arrancamos "server_a" docker stop server_a Al arrancarlo: docker stop server_a NO nos da ningún error. Si hubiésemos usado la opción "--link" no hubiéramos podido arrancarlo 6. Repetir el paso 3. Debemos obtener el mismo resultado 7. Limpiamos docker stop server_a && docker rm server_a docker stop server_b && docker rm server_b docker stop server_c && docker rm server_c docker network rm network-private ==== Con docker compose ==== 1. Crear el siguiente archivo: version: '3.7' services: server_a: container_name: server_a image: debian stdin_open: true tty: true networks: network-private: aliases: - server_a server_b: container_name: server_b image: debian stdin_open: true tty: true networks: network-private: aliases: - server_b server_c: container_name: server_c image: debian stdin_open: true tty: true networks: network-private: name: network-private 2. Levantar el entorno: docker-compose up -d 3. Realizar las mismas pruebas que en el apartado anterior (re-crear el contenedor se tendrá que hacer a mano, sin docker-compose) 4. Para limpiar: 4.1. Eliminar a mano "server_b" docker stop server_b && docker rm server_b 4.2. Pararlo todo docker-compose down ====== Puertos ====== Para especificar, por ejemplo, que el puerto 8000 del host se conecta al puerto 80 del contenedor: docker run -d -p 8000:80 training/webapp python app.py ====== Sistema de archivos ====== * Montar un volumen del anfitrion como volumen de datos en el contenedor: docker run -d -P --name web -v /host/dir:/container/dir training/webapp python app.py * Crear y montar un contenedor de volumen de datos docker create -v /dbdata --name dbdata training/postgres /bin/true docker run -d --volumes-from dbdata --name db1 training/postgres docker run -d --volumes-from dbdata --name db2 training/postgres etc... ====== Comandos varios ====== https://coderwall.com/p/ewk0mq/stop-remove-all-docker-containers * One liner to stop / remove all of Docker containers: docker stop $(docker ps -a -q) docker rm $(docker ps -a -q) * Obtener todos los contenedores: docker ps -a -q Comandos varios, luego se iran explicando: docker run -i -t ubuntu /bin/bash docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done" * Pre-descargar una imagen docker pull centos * Conectarse a un contenedor docker exec -u root -it container_name bash * Liberar espacio eliminando imagenes: docker images --no-trunc| grep none | awk '{print $3}' | xargs -r docker rmi * Eliminar imagenes: docker rmi mi_imagen * Obtener IP local del contenedor, una vez conocido el container ID docker inspect --format '{{ .NetworkSettings.IPAddress }}' container_id * Obtener puertos que tiene abiertos internamente (con jq): docker inspect container_id |jq .[].NetworkSettings.Ports * Renombrar container: docker rename CONTAINER NEW_NAME * Conectarse al terminal de un contenedor (debe haberse arrancado con -ti): docker attach my_container * Desconectarse de la consola sin detener el contenedor: CTRL + p + q ====== Imagenes ====== A continuacion una lista de imagenes y servicios y sus particularidades ===== Odoo ===== https://hub.docker.com/_/odoo/ ==== 8.x ==== Punto de partida: /srv/docker/data . +-- odoo-8 | +-- conf | +-- openerp-server.conf +-- odoo-9 | +-- conf | +-- openerp-server.conf +-- postgres-odoo-8 | +-- data +-- postgres-odoo-9 +-- data [[https://github.com/odoo/docker/blob/master/8.0/openerp-server.conf|Archivo de configuracion]] de Odoo: /srv/docker/data/odoo-9/conf/openerp-server.conf [options] addons_path = /usr/lib/python2.7/dist-packages/openerp/addons,/mnt/extra-addons data_dir = /var/lib/odoo auto_reload = True db_user = user db_password = secret ; admin_passwd = admin ; csv_internal_sep = , ; db_maxconn = 64 ; db_name = False ; db_template = template1 ; dbfilter = .* ; debug_mode = False ; email_from = False ; limit_memory_hard = 2684354560 ; limit_memory_soft = 2147483648 ; limit_request = 8192 ; limit_time_cpu = 60 ; limit_time_real = 120 ; list_db = True ; log_db = False ; log_handler = [':INFO'] ; log_level = info ; logfile = None ; longpolling_port = 8072 ; max_cron_threads = 2 ; osv_memory_age_limit = 1.0 ; osv_memory_count_limit = False ; smtp_password = False ; smtp_port = 25 ; smtp_server = localhost ; smtp_ssl = False ; smtp_user = False ; workers = 0 ; xmlrpc = True ; xmlrpc_interface = ; xmlrpc_port = 8069 ; xmlrpcs = True ; xmlrpcs_interface = ; xmlrpcs_port = 8071 Arrancar (por soleares) un contenedor con Postgres. En este ejemplo uso un directorio del host para almacenar la base de datos y el mismo usuario que hemos definido antes: docker run -d -e POSTGRES_USER=user -e POSTGRES_PASSWORD=secret -v /srv/docker/data/postgres-odoo-9/data:/var/lib/postgresql/data --name postgres-odoo-9 postgres Arrancar contenedor con odoo apuntando a ese contenedor postgresql y al archivo de config: docker run -p 127.0.0.1:8069:8069 --link postgres-odoo-9:db -t -v /srv/docker/data/odoo-9/conf:/etc/odoo --name odoo-9 odoo Probar: http://localhost:8069 ==== 10.x ==== Creo que no hay cambio respecto a la 8.0: 1. Lanzar un contender con la base de datos Postgre: docker run --name odoo10-db \ -e POSTGRES_USER=odoo \ -e POSTGRES_PASSWORD=odoo \ -v /home/usuario/data/docker/data/odoo10-db:/var/lib/postgresql/data \ -d postgres:9.4 2. Lanzar el contenedor con Odoo: docker run --name odoo10 \ -p 8069:8069 \ --link odoo10-db:db \ -v /home/usuario/data/docker/data/odoo10:/etc/odoo \ -d odoo 3. Acceder: http://localhost:8069 ===== PHP ===== * Escucha en el puerto 8000 * Dejar en el directorio del host "/srv/docker/5-apache" las webs a servir * Enlazo con un docker "mariadb" para poder usarlo como base de datos, le llamaré "mysql" docker run --name 7-apache \ -p 8000:80 \ --link mariadb:mysql \ -v /home/usuario/data/docker/data/7-apache:/var/www/html \ -d php:7-apache ==== Instalar módulos PHP ==== **AVISO**: si se usa un php.ini propio cascará la instalación, habrá que referenciar en ese archivo las rutas a los .po que toque Instalar bibliotecas necesarias para trabajar con MySQL/MariaDB: 1. Nos conectamos al contenedor docker exec -u root -it 5-apache bash 2. Instalamos (ver documentación de esa imagen de docker) * Para imagen de PHP 5 docker-php-ext-install mysql mysqli pdo pdo_mysql * Para imagen de PHP 7 docker-php-ext-install mysqli pdo pdo_mysql 2.1. **Caso especial: GD** apt-get update apt-get install libpng-dev docker-php-ext-install gd 2.2. **Caso especial: mcrypt** * Para imagen PHP <7.2 apt-get update apt-get install libmcrypt-dev docker-php-ext-install mcrypt * Para imagen PHP >=7.2 pecl install mcrypt-1.0.1 docker-php-ext-install mcrypt TODO: (PHP >=7.2) ver si se ha instalado realmente o no: install ok: channel://pecl.php.net/mcrypt-1.0.1 configuration option "php_ini" is not set to php.ini location You should add "extension=mcrypt.so" to php.ini 3. Salimos exit 4. (Desde el host) Reiniciamos el contenedor para que los cambios tomen efecto: docker restart 5-apache ==== Habilitar mod_rewrite ==== docker exec 5-apache a2enmod rewrite docker exec 5-apache service apache2 restart A mi se me paró el contenedor, arrancarlo pues: docker start 5-apache ===== MariaDB ===== * Almacena las bases de datos en el directorio del host "/srv/docker/data/mariadb/databases" * Toma config adicional del directorio "/srv/docker/data/mariadb/config": +-- mariadb +-- config | +-- custom.cnf +-- databases **custom.cnf** [mysqld] bind-address=0.0.0.0 docker run --name mariadb \ -v /home/usuario/data/docker/data/mariadb/databases:/var/lib/mysql \ -v /home/usuario/data/docker/data/mariadb/config:/etc/mysql/conf.d \ -e MYSQL_ROOT_PASSWORD=mysecret \ -d mariadb:latest * Para hacer una ingesta de archivo .sql: docker exec -i mariadb mysql -u root -psecret < /path/to/file.sql * Para interactuar vía cliente mysql (ya NO es necesario el "export TERM=dumb"): docker exec -ti mariadb bash mysql -u root -p grant all on db.* to 'db'@'%' identified by 'db'; flush privileges; exit; Configuración que viene por defecto: # MariaDB database server configuration file. # # You can copy this file to one of: # - "/etc/mysql/my.cnf" to set global options, # - "~/.my.cnf" to set user-specific options. # # One can use all long options that the program supports. # Run program with --help to get a list of available options and with # --print-defaults to see which it would actually understand and use. # # For explanations see # http://dev.mysql.com/doc/mysql/en/server-system-variables.html # This will be passed to all mysql clients # It has been reported that passwords should be enclosed with ticks/quotes # escpecially if they contain "#" chars... # Remember to edit /etc/mysql/debian.cnf when changing the socket location. [client] port = 3306 socket = /var/run/mysqld/mysqld.sock # Here is entries for some specific programs # The following values assume you have at least 32M ram # This was formally known as [safe_mysqld]. Both versions are currently parsed. [mysqld_safe] socket = /var/run/mysqld/mysqld.sock nice = 0 [mysqld] skip-host-cache skip-name-resolve # # * Basic Settings # #user = mysql pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock port = 3306 basedir = /usr datadir = /var/lib/mysql tmpdir = /tmp lc_messages_dir = /usr/share/mysql lc_messages = en_US skip-external-locking # # Instead of skip-networking the default is now to listen only on # localhost which is more compatible and is not less secure. #bind-address = 127.0.0.1 # # * Fine Tuning # max_connections = 100 connect_timeout = 5 wait_timeout = 600 max_allowed_packet = 16M thread_cache_size = 128 sort_buffer_size = 4M bulk_insert_buffer_size = 16M tmp_table_size = 32M max_heap_table_size = 32M # # * MyISAM # # This replaces the startup script and checks MyISAM tables if needed # the first time they are touched. On error, make copy and try a repair. myisam_recover_options = BACKUP key_buffer_size = 128M #open-files-limit = 2000 table_open_cache = 400 myisam_sort_buffer_size = 512M concurrent_insert = 2 read_buffer_size = 2M read_rnd_buffer_size = 1M # # * Query Cache Configuration # # Cache only tiny result sets, so we can fit more in the query cache. query_cache_limit = 128K query_cache_size = 64M # for more write intensive setups, set to DEMAND or OFF #query_cache_type = DEMAND # # * Logging and Replication # # Both location gets rotated by the cronjob. # Be aware that this log type is a performance killer. # As of 5.1 you can enable the log at runtime! #general_log_file = /var/log/mysql/mysql.log #general_log = 1 # # Error logging goes to syslog due to /etc/mysql/conf.d/mysqld_safe_syslog.cnf. # # we do want to know about network errors and such #log_warnings = 2 # # Enable the slow query log to see queries with especially long duration #slow_query_log[={0|1}] slow_query_log_file = /var/log/mysql/mariadb-slow.log long_query_time = 10 #log_slow_rate_limit = 1000 #log_slow_verbosity = query_plan #log-queries-not-using-indexes #log_slow_admin_statements # # The following can be used as easy to replay backup logs or for replication. # note: if you are setting up a replication slave, see README.Debian about # other settings you may need to change. #server-id = 1 #report_host = master1 #auto_increment_increment = 2 #auto_increment_offset = 1 #log_bin = /var/log/mysql/mariadb-bin #log_bin_index = /var/log/mysql/mariadb-bin.index # not fab for performance, but safer #sync_binlog = 1 expire_logs_days = 10 max_binlog_size = 100M # slaves #relay_log = /var/log/mysql/relay-bin #relay_log_index = /var/log/mysql/relay-bin.index #relay_log_info_file = /var/log/mysql/relay-bin.info #log_slave_updates #read_only # # If applications support it, this stricter sql_mode prevents some # mistakes like inserting invalid dates etc. #sql_mode = NO_ENGINE_SUBSTITUTION,TRADITIONAL # # * InnoDB # # InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/. # Read the manual for more InnoDB related options. There are many! default_storage_engine = InnoDB # you can't just change log file size, requires special procedure #innodb_log_file_size = 50M innodb_buffer_pool_size = 256M innodb_log_buffer_size = 8M innodb_file_per_table = 1 innodb_open_files = 400 innodb_io_capacity = 400 innodb_flush_method = O_DIRECT # # * Security Features # # Read the manual, too, if you want chroot! # chroot = /var/lib/mysql/ # # For generating SSL certificates I recommend the OpenSSL GUI "tinyca". # # ssl-ca=/etc/mysql/cacert.pem # ssl-cert=/etc/mysql/server-cert.pem # ssl-key=/etc/mysql/server-key.pem # # * Galera-related settings # [galera] # Mandatory settings #wsrep_on=ON #wsrep_provider= #wsrep_cluster_address= #binlog_format=row #default_storage_engine=InnoDB #innodb_autoinc_lock_mode=2 # # Allow server to accept connections on all interfaces. # #bind-address=0.0.0.0 # # Optional setting #wsrep_slave_threads=1 #innodb_flush_log_at_trx_commit=0 [mysqldump] quick quote-names max_allowed_packet = 16M [mysql] #no-auto-rehash # faster start of mysql but no tab completion [isamchk] key_buffer = 16M # # * IMPORTANT: Additional settings that can override those from this file! # The files must end with '.cnf', otherwise they'll be ignored. # !includedir /etc/mysql/conf.d/ ===== Zabbix ===== ==== Zabbix Server ===== https://hub.docker.com/r/zabbix/zabbix-server-mysql/ docker run --name zabbix-server \ --link mariadb:mysql \ -e DB_SERVER_HOST="mariadb" \ --link mariadb:mysql \ -e MYSQL_DATABASE="zabbix_server" \ -e MYSQL_USER="zabbix_server" \ -e MYSQL_PASSWORD="zabbix_server" \ -v /home/usuario/data/docker/data/zabbix-server/externalscripts:/usr/lib/zabbix/externalscripts \ -d zabbix/zabbix-server-mysql ==== Zabbix Web ===== docker run --name zabbix-web \ --link zabbix-server:zabbix-server \ --link mariadb:mysql \ -e DB_SERVER_HOST="mariadb" \ -e MYSQL_DATABASE="zabbix_server" \ -e MYSQL_USER="zabbix_server" \ -e MYSQL_PASSWORD="zabbix_server" \ -e ZBX_SERVER_HOST="zabbix-server" \ -e TZ="Europe/Madrid" \ -p 8000:80 \ -d zabbix/zabbix-web-apache-mysql La base de datos que usa es la que provee el Zabbix Server al que se enlace. Se puede acceder a través de: http://localhost:8000 Usuario: Admin Contraseña: zabbix ====== Repositorios ====== ===== hub.docker.com ===== Tenemos una imagen y la queremos subir a nuestro repositorio hub de docker: # docker images REPOSITORY TAG IMAGE ID CREATED SIZE oraclelinux 6.6 9636e42b38e2 5 months ago 157.7 MB Le cambiamos el nombre al de nuestro repositorio: # docker tag 9636e42b38e2 iwanttobefreak/weblogic121 Nos logamos en nuestro repositorio: # docker login --username= --email= Subimos la imagen: # docker push iwanttobefreak/weblogic121 The push refers to a repository [docker.io/iwanttobefreak/weblogic121] 5f70bf18a086: Pushed 3b101413fff5: Pushed latest: digest: sha256:9acc7e03325faa04fe466d9b2c22c5241fb8c0c276e3bbcfeaa66714c894f98e size: 2 Nos crea un repositorio en nuestro hub de docker ===== Asociar hub de docker con github ===== Si queremos mantener nuestro docker desde github y que se generen las imagenes automáticamente: **Automated Build** Primero creamos nuestro repositorio en GitHub. Luego lo creamos en docker.Vamos a Create/Create Automated Build {{:informatica:linux:seleccion_999_213_.png|}} Seleccionamos GitHub y nuestro repositorio de github. Ponemos descripición y pulsamos create ===== Repositorio en local y GITHUB ===== Para descargar un repositorio de GITHUB: git clone https://github.com/iwanttobefreak/docker-weblogic1036.git Para subir el repositorio: git add git commit -m "cambio realizado" git push ===== Borrar containers e imagenes que no se usan ===== Borra los containers que no tengan guión "-" en el nombre y las imágenes sin repositorio: #!/bin/bash docker ps -a | awk {'print $NF'}| grep -v -E '\-|NAMES' | xargs -i docker rm {} docker images | awk '{if ( $1 == "" ) printf $3"\n"}' | xargs -i docker rmi {} Script de borrado de imagenes y containers huérfanos #!/bin/bash while read linea do docker rmi -f $linea done < <(docker images | awk '{if ( $2 == "" ) printf $3"\n"}') while read linea do imageid=`echo $linea|awk {'print $2'}` docker images| grep $imageid if [ `echo $?` -eq 1 ] then containerid=`echo $linea|awk {'print $1'}` echo "Borrando container: "$containerid" "$imageid docker rm $containerid fi done < <(docker ps -a ) ===== Docker en Glusterfs ===== Para poder correr docker en glusterfs cambiamos el sistema de archivos de aufs a devicemapper Si hacemos # docker info Storage Driver: aufs Lo cambiamos a devicemapper. Si usamos systemd es en el fichero: /etc/systemd/system/docker.service Cambiamos --storage-driver a devicemapper [Service] ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock --storage-driver devicemapper --tlsverify --tlscacert /etc/docker/ca.pem --tlscert /etc/docker/server.pem --tlskey /etc/docker/server-key.pem --label provider=generic Recargamos systemctl y reiniciamos docker systemctl daemon-reload /etc/init.d/docker restart Ya podemos escribir en glusterfs: Storage Driver: devicemapper ====== Arrancar contenedores automáticamente ====== https://docs.docker.com/engine/admin/start-containers-automatically/ docker update --restart=unless-stopped mycontainer ====== Docker compose ====== https://docs.docker.com/compose/ ===== Apache Php y Mysql ===== Levanta un frontend con apache y php que conecta con otro contendedor con mysql: docker-compose.yml version: '2' services: bbdd: image: mysql:5 environment: - MYSQL_ROOT_PASSWORD=dadada - MYSQL_DATABASE=prova - MYSQL_USER=armando - MYSQL_PASSWORD=bronca restart: always web: image: eboraas/apache-php links: - bbdd:bbdd ports: - 8081:80 volumes: - ./html/:/var/www/html/ restart: always Creamos el fichero dentro de la carpeta html/mysql.php \n"; while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) { echo "\t\n"; foreach ($line as $col_value) { echo "\t\t$col_value\n"; } echo "\t\n"; } echo "\n"; // Liberar resultados mysql_free_result($result); // Cerrar la conexión mysql_close($link); ?> ====== Estadísticas ====== Para mostrar estadísticas de consumo de recursos por contenedor: watch -n 5 'docker stats --no-stream --format "table {{.Name}}\t{{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" | sort -r -k 3 -h' ====== Usar variables de entorno en tiempo de arranque ====== 1. Crear script de arranque mkdir /tmp/aux cd /tmp/aux vim entrypoint.sh Con el siguiente contenido: #!/bin/bash echo "Content of VAR1 is: _"$VAR1"_" 2. Crear Dockerfile: cd /tmp/aux vim Dockerfile Con el siguiente contenido: FROM debian:testing COPY entrypoint.sh / RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] 3. Probar docker build . -t localhost/test && docker stop test && docker rm test && docker run --name test -ti -e VAR1=patata localhost/test La última linea de la salida debería ser: Content of VAR1 is: _patata_ 4. Limpiar docker stop test && docker rm test && docker rmi localhost/test ====== Timezone ====== Para ganar tiempo dejo algunos ejemplos de cómo configurar el timezone dependiendo de la imagen ===== Alpine ===== Hay que hacer 2 cosas: 1. Instalar el paquete "tzdata" apk add tzdata 2. Configurar la variable de entorno "TZ" ===== Debian (p.ej.python:3-stretch) ===== Hay que hacer 1 cosa: 1. Crear un enlace simbólico. En este ejemplo usamos la variable "$TZ", pero se puede "hardcodear" a "Europe/Madrid" por ejemplo ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone ====== Errores ====== ===== docker: Error response from daemon: rpc error: code = 2 desc = "oci runtime error: could not synchronise with container process: no subsystem for mount". ===== Parece que es debido a la instalación de docker, seguí las instrucciones de instalación para debian y todo ok: https://docs.docker.com/engine/installation/linux/debian/ 1. Uninstall old versions sudo apt-get remove docker docker-engine 2. Set up the repository 2.1. Install packages to allow apt to use a repository over HTTPS: sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg2 \ software-properties-common 2.2. Add Docker’s official GPG key: curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - 2.3. Use the following command to set up the stable repository. You always need the stable repository, even if you want to install edge builds as well. sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/debian \ $(lsb_release -cs) \ stable" 3. Install Docker CE sudo apt-get update; sudo apt-get install docker-ce ===== Forzar detención contenedor estado "restart" ===== Escenario: 1. Hemos detenido un contenedor cuya política de reinicio era "unless-stopped": docker stop dns dns 2. El contenedor está en estado "restart": docker ps | grep dns 5cb2e9ca4508 keducoop/dns:v2 "./dockerdns --domai…" 3 months ago Restarting (1) About an hour ago 0.0.0.0:53->53/udp dns **Solución** 1. Cambiar la política de reinicio del contenedor a "no": docker update --restart=no dns dns 2. Ahora **SI** se podrá detener el contenedor sin que vuelva a intentar iniciarse: docker stop dns dns Comprobar: docker ps | grep dns ===== ERROR: Service 'logrotate' failed to build: invalid reference format ===== Escenario: * Uso docker compose * Uso build dentro del docker compose * La imagen y la versión se pasan por parámetro **docker-compose.yml** version: '3.7' services: logrotate: build: context: ./path/to/dir args: - IMAGE=${IMAGE} - VERSION=${VERSION} ... **Dockerfile** (dentro de './path/to/dir') ARG IMAGE ARG VERSION FROM $IMAGE:$VERSION ... **.env** IMAGE= VERSION=latest Solución: Revisar que las variables "IMAGE" y "VERSION" sean coherentes. En este caso por error IMAGE estaba vacía ===== ERROR: yaml.parser.ParserError: while parsing a block mapping ===== Error completo: ERROR: yaml.parser.ParserError: while parsing a block mapping in "./docker-compose.analytics-celery-v3.yml", line 1, column 1 expected , but found '' in "./docker-compose.analytics-celery-v3.yml", line 14, column 2 Asegurarse que todos los servicios están alineados a la misma altura. **KO** version: '3.7' services: logrotate-legacy: build: context: ./services/logrotate/ dockerfile: Dockerfile container_name: logrotate-legacy environment: - LOGROTATE_LOGFILES=/var/log/plc/*.log volumes: - /var/log/plc/:/var/log/plc/:rw logrotate: container_name: ${LOGROTATE_NAME} image: ${LOGROTATE_IMAGE_LOCAL}/${LOGROTATE_NAME}:${LOGROTATE_VERSION} restart: ${LOGROTATE_RESTART} volumes: - ${LOGROTATE_VOLUME_PLC_HOST}:${LOGROTATE_VOLUME_PLC_CONTAINER} build: #context: ./services/logrotate context: ./services/logrotate-v2/ args: - IMAGE=${LOGROTATE_IMAGE} - VERSION=${LOGROTATE_VERSION} - LOGROTATE_LOGFILES=${LOGROTATE_LOGROTATE_LOGFILES} networks: network-logrotate: name: ${NETWORK_LOGROTATE} **OK** version: '3.7' services: logrotate-legacy: build: context: ./services/logrotate/ dockerfile: Dockerfile container_name: logrotate-legacy environment: - LOGROTATE_LOGFILES=/var/log/plc/*.log volumes: - /var/log/plc/:/var/log/plc/:rw logrotate: container_name: ${LOGROTATE_NAME} image: ${LOGROTATE_IMAGE_LOCAL}/${LOGROTATE_NAME}:${LOGROTATE_VERSION} restart: ${LOGROTATE_RESTART} volumes: - ${LOGROTATE_VOLUME_PLC_HOST}:${LOGROTATE_VOLUME_PLC_CONTAINER} build: #context: ./services/logrotate context: ./services/logrotate-v2/ args: - IMAGE=${LOGROTATE_IMAGE} - VERSION=${LOGROTATE_VERSION} - LOGROTATE_LOGFILES=${LOGROTATE_LOGROTATE_LOGFILES} networks: network-logrotate: name: ${NETWORK_LOGROTATE} ===== does not match any of the regexes: '^x-' ===== Error completo: ERROR: The Compose file './docker-compose.rafa.yml' is invalid because: networks.network-rafa-db value 'network-proxy' does not match any of the regexes: '^x-' **Causa** Un bloque, en este caso dentro de networks, no está alineado correctamente **Solución** 1. Identificar el bloque, en este caso "networks" 2. Revisar las entradas. Una de ellas tiene un espacio de más o de menos ===== Servidor tarda en apagarse esperando por contenedores docker ===== https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=989490#14 ===== Docker build con variables ===== Si queremos tener versionado un docker, por ejemplo con versiones diferentes de node.js desde el build.\\ Instala por defecto la version 16.13.0 FROM debian ARG NODE_VERSION=16.13.0 RUN wget https://nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz RUN mkdir -p /usr/local/lib/nodejs RUN tar -xJvf node-v$NODE_VERSION-linux-x64.tar.xz -C /usr/local/lib/nodejs CMD ["bash", "-l"] Si quisiera crear una imagen con otra versión: docker build --build-arg NODE_VERSION=18.15.0 -f Dockerfile -t node:18.15 .