Инструменты пользователя

Инструменты сайта


service:docker

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
service:docker [05.02.2025 12:44] – [Buildx / Buildkit] viacheslavservice:docker [23.05.2025 12:55] (текущий) – [Сделать сеть с другим именем, не прописывая её явно для всех сервисов] viacheslav
Строка 1: Строка 1:
 +====== Docker ======
 +<WRAP right box 25%>
 +— What is the first clue to build the container?\\
 +— It must be bound in thews of invincible iron.\\
 +— What is the second clue to build the container?\\
 +— Bejewel the chest with the hallowed heart of glittering stone.\\
 +— What is the third clue to build the container?\\
 +— Gift it with the essence of dragon amber, born of earth and root.\\
 +— What is the fourth clue to build the container?\\
 +— A sacrifice of clay. The power to bind its parts.\\
 +— What is the fifth clue to build the container?\\
 +— Craft it from wood no mortal blade can carve. Find the wicked tree.\\
 +— What is the sixth clue to build the container?\\
 +— The strength of love denied. The soul of a dead hero shall empower it.\\
 +— What is the seventh clue to build the container?\\
 +— Temper it in the tears of the weeping moon.\\
 +— What is the eighth clue to build the container?\\
 +— Forged by the legendary Black Gnarl, beneath his binding song.\\
 +— Each of the hearts have I given.\\
 +— And each of the riddles have I returned. I am free! Stay at your task, my fool. No greater curse might I impart!
  
 +//Anvil of Dawn//
 +</WRAP>
 +
 +===== Обновление =====
 +<code bash>
 +# pull latest images
 +docker-compose pull
 +# restart containers
 +docker-compose up -d --remove-orphans
 +# remove obsolete images
 +docker image prune
 +</code>
 +https://stackoverflow.com/questions/49316462/how-to-update-existing-images-with-docker-compose
 +
 +==== Buildx / Buildkit ====
 +Новый сборщик образов, который не требует установленного Docker engine. Это позволяет, например, собирать образы в кластере k8s.
 +
 +Установка
 +<code bash>
 +sudo apt install docker-buildx
 +</code>
 +
 +Сделать Buildkit сборщиком по умолчанию
 +<file json /etc/docker/daemon.json>
 +{
 +  "features": {
 +    "buildkit": true
 +  }
 +}
 +</file>
 +
 +<code bash>
 +sudo systemctl restart docker.service
 +</code>
 +
 +Если Buildkit не установлен по умолчанию, то запустить сборку через него можно через переменную.
 +<code bash>
 +DOCKER_BUILDKIT=1 docker build -t my_image .
 +</code>
 +https://docs.docker.com/build/buildkit/
 +===== Чистка =====
 +<file bash /etc/crontab>
 +### Docker cleaning
 +0 3     * * 2,4,6       root  docker container prune -f; docker image prune -af
 +0 3     * * 7           root  docker system prune -f
 +</file>
 +https://docs.docker.com/config/pruning/
 +
 +===== Тома для постоянного хранения =====
 +
 +==== sshfs ====
 +[[https://github.com/vieux/docker-volume-sshfs|sshfs]] монтирует каталог с другого сервера через SSH. 
 +<code bash>
 +### На сервере хранения:
 +# Создать каталог для тома (он должен быть, автоматически не создаётся):
 +mkdir -p /home/user/dockervol/bepasty
 +# Создать файл dump (иначе volume не подмонтируется, будет ошибка lchown permission denied, это проблема sshfs)
 +touch /home/user/dockervol/bepasty/dump
 +
 +### На сервере докера:
 +# Установка дополнения sshfs
 +docker plugin install --grant-all-permissions vieux/sshfs
 +</code>
 +https://github.com/vieux/docker-volume-sshfs/issues/76
 +
 +Пример с паролем, лучше через переменные или через ключи.
 +<code yaml>
 +version: '3.9'
 +
 +services:
 +  bepasty:
 +    build: .
 +    container_name: bepasty
 +    restart: unless-stopped
 +    volumes:
 +      - bepasty:/storage
 +    ports:
 +      - 80:5000
 +
 +volumes:
 +  bepasty:
 +    name: "bepasty"
 +    driver: "vieux/sshfs:latest"
 +    driver_opts:
 +      sshcmd: "user@server1:/home/user/dockervol/bepasty"
 +      password: "P@ssw0rd"
 +</code>
 +https://docs.docker.com/storage/volumes/#share-data-between-machines
 +
 +==== Резервное копирование тома ====
 +С помощью другого контейнера, который подключается к томам основного.
 +<code bash>
 +# Запуск 
 +docker run -d -v /dbdata --name dbstore alpine sleep infinity
 +# Создание файла
 +docker exec -it dbstore sh -c "echo 'Hello' >> /dbdata/file.txt"
 +# Проверка
 +docker exec -it dbstore sh -c "cat /dbdata/file.txt"
 +
 +# Бэкап
 +docker run --rm --volumes-from dbstore -v $(pwd):/backup alpine tar cvf /backup/backup.tar /dbdata
 +
 +# Запуск второго контейнера
 +docker run -d -v /dbdata --name dbstore2 alpine sleep infinity
 +# Восстановление из архива
 +docker run --rm --volumes-from dbstore2 -v $(pwd):/backup alpine sh -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1"
 +# Проверка
 +docker exec -it dbstore2 sh -c "cat /dbdata/file.txt"
 +</code>
 +https://docs.docker.com/storage/volumes/#back-up-restore-or-migrate-data-volumes
 +===== Мониторинг =====
 +==== Healthcheck ====
 +Можно делать в Dockerfile, можно в docker-compose.yml
 +
 +Варианты строки проверки
 +<code bash>
 +curl --fail http://localhost:8080/health
 +# иногда curl-а нет в образе, тогда
 +wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
 +</code>
 +https://docs.docker.com/engine/reference/builder/#healthcheck\\
 +https://docs.docker.com/compose/compose-file/#healthcheck\\
 +https://medium.com/geekculture/how-to-successfully-implement-a-healthcheck-in-docker-compose-efced60bc08e
 +==== Prometheus ====
 +/etc/prometheus/prometheus.yml
 +<code yaml>
 +# my global config
 +global:
 +  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
 +  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
 +  # scrape_timeout is set to the global default (10s).
 +
 +# Alertmanager configuration
 +alerting:
 +  alertmanagers:
 +  - static_configs:
 +    - targets:
 +      # - alertmanager:9093
 +
 +# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
 +rule_files:
 +  # - "first_rules.yml"
 +  # - "second_rules.yml"
 +
 +# A scrape configuration containing exactly one endpoint to scrape:
 +# Here it's Prometheus itself.
 +scrape_configs:
 +  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
 +  - job_name: 'prometheus'
 +    # metrics_path defaults to '/metrics'
 +    # scheme defaults to 'http'.
 +    static_configs:
 +    - targets: ['localhost:9090']
 +
 +  - job_name: 'docker'
 +    static_configs:
 +      - targets: ['172.17.0.1:9323']
 +
 +  - job_name: 'traefik'
 +    static_configs:
 +      - targets: ['traefik:8080']
 +</code>
 +**172.17.0.1 = host.docker.internal**\\
 +If you're running with ''--net=host'', ''localhost'' should work fine.\\
 +If you're using default networking, use the static IP ''172.17.0.1''. I suspect neither will behave quite the same as those domains.\\
 +https://stackoverflow.com/questions/48546124/what-is-linux-equivalent-of-host-docker-internal
 +
 +==== Dozzle ====
 +<code bash>
 +# На удалённом хосте запустить докер-прокси, чтобы можно было подключиться удалённо
 +docker container run --rm --name dockerproxy -e CONTAINERS=1 -v /var/run/docker.sock:/var/run/docker.sock -p 2375:2375 tecnativa/docker-socket-proxy
 +# Запустить Dozzle (будет мониториться как локальный сервер через сокет, так и удалённый через прокси)
 +docker run --rm --name dozzle -p 9999:8080 -v /var/run/docker.sock:/var/run/docker.sock amir20/dozzle:latest --base /logs --remote-host tcp://192.168.1.8:2375
 +</code>
 +https://github.com/amir20/dozzle\\
 +https://dozzle.dev/guide/remote-hosts\\
 +https://github.com/Tecnativa/docker-socket-proxy
 +
 +<WRAP group>
 +<WRAP half column>
 +Докер-прокси:
 +<file yaml docker-compose.yml>
 +version: '3.7'
 +
 +services:
 +  docker-proxy:
 +    image: tecnativa/docker-socket-proxy
 +    container_name: docker-proxy
 +    restart: unless-stopped
 +    volumes:
 +      - /var/run/docker.sock:/var/run/docker.sock
 +    environment:
 +      CONTAINERS: "1"
 +    ports:
 +      - 2375:2375
 +</file>
 +</WRAP>
 +
 +<WRAP half column>
 +Dozzle (на другом сервере, локальный Докер не мониторится)
 +<file yaml docker-compose.yml>
 +version: '3.7'
 +
 +services:
 +  dozzle:
 +    image: amir20/dozzle
 +    container_name: dozzle
 +    restart: unless-stopped
 +    environment:
 +      DOZZLE_BASE: "/dockerlogs"
 +      DOZZLE_REMOTE_HOST: "tcp://server1:2375,tcp://server2:2375"
 +    ports:
 +      - 8080:8080
 +</file>
 +</WRAP>
 +</WRAP>
 +
 +===== Деплой =====
 +==== Blue-green ====
 +<code bash>
 +#!/bin/bash
 +
 +replicas=2
 +
 +function deploybg {
 +  docker-compose rm -sf $2
 +  docker-compose pull $2
 +  docker-compose up -d --scale $2=$replicas --force-recreate $2
 +  until [[ ${#count[@]} = $replicas ]]; do
 +    count=( $(docker ps -qf name=$2 -f health=healthy) )
 +    sleep 10
 +  done
 +  docker-compose rm -sf $1
 +}
 +
 +if [[ $(docker ps -qf name=backend-blue) ]]
 +then
 +  deploybg backend-blue backend-green
 +else
 +  deploybg backend-green backend-blue
 +fi
 +</code>
 +
 +В Gitlab (1 реплика и удалённый контекст, т. к. непонятно, как экранировать #):
 +<code bash>
 +script:
 +    - docker context create remote --docker "host=ssh://${USER}@${HOST}"
 +    - docker context use remote
 +    - |
 +      function deploybg {      
 +        docker-compose --context remote rm -sf $2
 +        docker-compose --context remote pull $2
 +        docker-compose --context remote up -d --force-recreate $2
 +        until [[ $(docker ps -qf name=$2 -f health=healthy) ]]
 +        do
 +          sleep 10
 +        done
 +        docker-compose --context remote rm -sf $1
 +      }
 +      if [[ $(docker ps -qf name=backend-blue) ]]
 +      then
 +        deploybg backend-blue backend-green
 +      else
 +        deploybg backend-green backend-blue
 +      fi 
 +</code>
 +
 +===== Хранение данных =====
 +
 +[[https://gist.github.com/scyto/f4624361c4e8c3be2aad9b3f0073c7f9|My Docker Swarm Architecture]] (GlusterFS)
 +
 +===== Решение проблем =====
 +==== Cannot start service <servicename>: get <id>: no such volume ====
 +<code>
 +Starting bepasty ... error
 +ERROR: for bepasty  Cannot start service bepasty: get 441a8f149da5cbd4fe25591303b0d7885f085729819c5b8aef52dd22b25b1072: no such volume
 +ERROR: for bepasty  Cannot start service bepasty: get 441a8f149da5cbd4fe25591303b0d7885f085729819c5b8aef52dd22b25b1072: no such volume
 +ERROR: Encountered errors while bringing up the project.
 +</code>
 +Решение:
 +<code bash>
 +docker container prune
 +docker-compose up -d
 +</code>
 +
 +==== cannot stop container: permission denied ====
 +Невозможно остановить/удалить/пересоздать контейнеры, ошибки такие:
 +<code>
 +Error response from daemon: cannot stop container: c2a63f33d8b5: permission denied
 +Error response from daemon: Cannot kill container: c2a63f33d8b5: permission denied
 +</code>
 +Перезапуск ОС/Докера ничего не даёт
 +
 +Решение:
 +It turned out that AppArmor service was messing up with Docker. AppArmor (or “Application Armor”) is a Linux kernel security module that allows the system administrator to restrict programs’ capabilities with per-program profiles. For this problem with containers, it helped me to remove the unknown from AppArmor using the following command:
 +<code bash>
 +sudo aa-remove-unknown
 +</code>
 +After that, I was able to stop and kill my containers.
 +
 +https://debugah.com/solved-cannot-kill-docker-container-permission-denied-23902/
 +
 +==== Запустить команду с конвейером (pipe) в контейнере с хоста ====
 +<code bash>
 +# Use "docker exec" to change user password in container from host.
 +docker exec ops_ubuntu_ntp2 echo "cobra_demo:cobra_pw"|chpasswd
 +# Fail to user chpasswd to change password of user cobra_demo in container.
 +# This is because the Pipe (|).
 +# The command chpasswd is executed in host not in container. 
 +# However, host accept the output from docker container as it parameter.
 +
 +docker exec ops_ubuntu_ntp2 echo "cobra_demo:cobra_pw"
 +#try another way, use "echo" to pass parameter to "docker exec"
 +echo "cobra_demo:cobra_pw"|chpasswd | docker exec ops_ubuntu_ntp2 /bin/bash/
 +
 +# I tried many solution and found the following command works
 +# The -i parameter is must.
 +echo "echo cobra_demo:cobra_pw|chpasswd" | docker exec ops_ubuntu_ntp2 /bin/bash
 +
 +# Paramater -i for docker exec. I don't know why, but it works.
 +echo "echo cobra_demo:cobra_pw|chpasswd" | docker exec -i ops_ubuntu_ntp2 /bin/bash
 +</code>
 +https://www.youtube.com/watch?v=6fEmryhIbr4 (текст в описании)
 +
 +==== Блокировка dockerhub.io в России ====
 +С 30 мая 2024 г.
 +
 +1. Конфиг докера (как зеркало docker.io)
 +^операционная система ^путь к файлу конфигурации ^
 +|Linux, regular setup |''/etc/docker/daemon.json'' |
 +|Linux, rootless mode |''~/.config/docker/daemon.json'' |
 +|Windows |''C:\ProgramData\docker\config\daemon.json'' |
 +
 +<code bash>
 +cat << EOF |sudo tee -a /etc/docker/daemon.json
 +{
 +  "registry-mirrors": [
 +    "https://mirror.gcr.io",
 +    "https://dockerhub.timeweb.cloud",
 +    "https://daocloud.io",
 +    "https://c.163.com",
 +    "https://huecker.io",
 +    "https://registry.docker-cn.com"
 +  ]
 +}
 +EOF
 +</code>
 +Теперь, при попытке загрузки образа, докер будет сначала пытаться использовать прокси.
 +
 +2. Явное указание адреса
 +<code bash>
 +docker pull mirror.gcr.io/library/alpine:latest
 +</code>
 +
 +https://huecker.io/\\
 +https://habr.com/ru/news/818177/comments/
 +
 +==== docker.errors.DockerException: Error while fetching server API version ====
 +На новых системах после установки docker-compose и попыткой им воспользоваться выходит ошибка\\
 +<color #ed1c24>docker.errors.DockerException: Error while fetching server API version: HTTPConnection.request() got an unexpected keyword argument ‘chunked’</color>
 +
 +Решение: снести старый docker-compose и установить docker-compose-v2.
 +<code bash>
 +sudo apt remove docker-compose -y
 +sudo apt install docker-compose-v2 -y
 +</code>
 +После этого команды выглядят так:
 +<code bash>
 +# без дефиса
 +docker compose up -d
 +docker compose ps
 +# и т. д.
 +</code>
 +===== Полезное =====
 +==== Запуск контейнера не от root ====
 +  - [[https://americanexpress.io/do-not-run-dockerized-applications-as-root/|Don’t run Docker container processes as root]]. Santa won’t bring you any gifts if you use root.
 +  - Use [[https://github.com/ncopa/su-exec#why-reinvent-gosu|su-exec]], [[https://github.com/tianon/gosu|gosu]], chroot, or [[https://manpages.debian.org/buster/util-linux/setpriv.1.en.html|setpriv]] to step down from root into another user inside your Docker containers.
 +  - You can use Supervisor to manage processes in Docker containers and step down from root. But unless you have [[https://advancedweb.hu/supervisor-with-docker-lessons-learned/|a very specific use case to do so]], you shouldn’t because it’s at least 50MB heavier.
 +
 +su-exec is a new-ish alternative to gosu. Both provide similar functionality, but su-exec weights only 10kb instead of 1.8MB.
 +
 +This shows how to:
 +
 +  - Install php7-fpm and su-exec on an Alpine 3.11 Docker image;
 +  - Step down from user root into user nobody using su-exec, and;
 +  - Execute php-fpm using su-exec:
 +<code>
 +FROM alpine:3.11
 +RUN apk add --no-cache php7-fpm su-exec
 +ENTRYPOINT ["su-exec", "nobody", "/usr/sbin/php-fpm7", "--nodaemonize", "--force-stderr"]
 +</code>
 +
 +==== Docker Swarm - запуск команды в контейнере сервиса ====
 +Чтобы не искать имя контейнера в сервисе. Надо выбирать имя, которое однозначно указывает на сервис, а то можно получить не тот результат, если запрос совпадает с несколькими сервисами.
 +<code bash>
 +docker exec $(docker ps -q -f name='lk_frontend_nginx' |head -n 1) ls
 +</code>
 +
 +==== Права ====
 +В контейнере PHP и Nginx есть юзер www-data (ID 33), которого можно использовать вместо рута при совместной работе.
 +
 +<file bash Dockerfile>
 +FROM composer AS vendor
 +WORKDIR /app
 +
 +COPY composer.json .
 +RUN composer install --ignore-platform-reqs --no-dev --no-scripts
 +
 +
 +FROM php:8.0-fpm
 +COPY --chown=33:33 --from=vendor /app/vendor ./vendor
 +
 +RUN \
 +apt update && apt install -y --no-install-recommends \
 +libzip-dev \
 +libpng-dev \
 +libxml2-dev && \
 +docker-php-ext-install \
 +pdo_mysql \
 +exif \
 +pcntl \
 +bcmath \
 +gd \
 +soap \
 +zip \
 +sockets
 +
 +USER 33
 +</file>
 +
 +То же самое, только размер в 5 раз меньше
 +<code bash Dockerfile>
 +FROM composer AS vendor
 +WORKDIR /app
 +
 +COPY composer.json .
 +RUN composer install --ignore-platform-reqs --no-ansi --no-dev --no-interaction --no-progress --no-scripts --optimize-autoloader
 +
 +FROM alpine:3.16
 +WORKDIR /var/www/html
 +
 +RUN apk add --no-cache \
 +php8 \
 +php8-fpm \
 +php8-mbstring \
 +php8-pdo_mysql \
 +php8-exif \
 +php8-pcntl \
 +php8-bcmath \
 +php8-gd \
 +php8-soap \
 +php8-zip \
 +php8-sockets \
 +php8-session \
 +php8-fileinfo && \
 +addgroup -g 82 -S www-data || true && \
 +adduser -u 82 -D -S -G www-data www-data || true && \
 +sed -i '/listen = /c listen = 0.0.0.0:9000' /etc/php8/php-fpm.d/www.conf && \
 +chown -R 82: /var/log/php*
 +#sed -i '/user =/c user = www-data' /etc/php8/php-fpm.d/www.conf && \
 +#sed -i '/group =/c group = www-data' /etc/php8/php-fpm.d/www.conf && \
 +#sed -i '/php_admin_value\[memory_limit\] = /c php_admin_value[memory_limit] = 512M' /etc/php8/php-fpm.d/www.conf && \
 +#sed -i '/memory_limit = /c memory_limit = 512M' /etc/php8/php.ini && \
 +#sed -i 's/;clear_env/clear_env/' /etc/php8/php-fpm.d/www.conf && \
 +#sed -i 's/^;env/env/' /etc/php8/php-fpm.d/www.conf
 +
 +COPY --chown=82:82 --from=vendor /app/vendor ./vendor
 +COPY --chown=82:82 . .
 +
 +EXPOSE 9000
 +#websockets
 +#EXPOSE 6001
 +
 +USER 82
 +
 +#RUN php artisan key:generate
 +
 +CMD ["php-fpm8", "-F"]
 +</code>
 +
 +https://hub.docker.com/_/composer\\
 +https://hub.docker.com/_/php\\
 +http://www.inanzzz.com/index.php/post/k4r7/using-docker-multi-stage-builds-to-run-composer-install-and-copy-application-into-php-container-image\\
 +https://dev.to/mtk3d/read-this-before-you-start-using-the-multistage-builds-for-your-docker-images-21e7\\
 +https://laravel-news.com/multi-stage-docker-builds-for-laravel\\
 +https://nsirap.com/posts/039-docker-best-practice-multi-stage-build/\\
 +
 +В стандартных томах владелец меняется на папке _data, т. е.
 +<code bash>
 +docker run --rm -it -v alpinetest:/alpinetest alpine:3.16 sh
 +chown -R 82: /alpinetest
 +# На хосте:
 +ls -l /var/lib/docker/volumes
 +drwx-----x 3 root root   4.0K Jun 13 11:07 alpinetest
 +ls -l /var/lib/docker/volumes/alpinetest
 +drwxr-xr-x 2 82 82 4.0K Jun 13 11:09 _data
 +</code>
 +==== nginx ====
 +Шаблон конфигурации - берёт переменные окружения и поставляет их в шаблон, а потом пишет как файл конфигурации, убирая ''.template'' из имени файла.\\
 +Стандартный путь к шаблонам: ''/etc/nginx/templates/''\\
 +Стандартный путь к конфигурациям: ''/etc/nginx/conf.d/''
 +<file bash default.conf.template>
 +server {
 +    listen 80;
 +    index index.php index.html;
 +    root ${NGINX_ROOT};
 +    location ~ \.php$ {
 +        try_files $uri =404;
 +        fastcgi_split_path_info ^(.+\.php)(/.+)$;
 +        fastcgi_pass ${NGINX_FASTCGI_PASS}:9000;
 +        fastcgi_index index.php;
 +        include fastcgi_params;
 +        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 +        fastcgi_param PATH_INFO $fastcgi_path_info;
 +    }
 +    location / {
 +        try_files $uri $uri/ /index.php?$query_string;
 +        gzip_static on;
 +    }
 +}
 +</file>
 +
 +<file bash Dockerfile>
 +FROM nginx:alpine
 +
 +COPY default.conf.template /etc/nginx/templates/
 +</file>
 +
 +<file yaml docker-compose.yml>
 +version: "3.7"
 +service:
 +  nginx:
 +    build: ./nginx
 +    container_name: nginx
 +    environment:
 +      NGINX_ROOT: /var/www/html/public
 +      NGINX_FASTCGI_PASS: app
 +    volumes_from:
 +      - app
 +    ports:
 +      - 80:80
 +</file>
 +https://github.com/docker-library/docs/tree/master/nginx#using-environment-variables-in-nginx-configuration\\
 +==== PHP ====
 +В alpine:3.18 - версии 8.1 и 8.2\\
 +В alpine:3.17 - версия 8.1\\
 +В alpine:3.16 - версии 8 и 8.1 (по умолчанию ''apk add php'' ставится 8)
 +
 +[[https://dev.to/mtk3d/how-to-configure-php-logs-for-docker-2384|How to configure PHP logs for Docker]]
 +
 +[[https://github.com/renatomefi/php-fpm-healthcheck|php-fpm healthcheck]]
 +==== Laravel ====
 +
 +Пример проекта на Laravel - Pixelfed: https://docs.pixelfed.org/running-pixelfed/installation/
 +
 +[[https://laravel-news.com/laravel-scheduler-queue-docker|Running the Laravel Scheduler and Queue with Docker ]]\\
 +[[https://stackoverflow.com/questions/27674597/laravel-daily-log-created-with-wrong-permissions|Laravel daily log created with wrong permissions]]\\
 +[[https://www.8host.com/blog/zapusk-prilozheniya-laravel-cherez-docker-compose/|Запуск приложения Laravel через Docker Compose]]\\
 +[[https://www.digitalocean.com/community/tutorials/how-to-containerize-a-laravel-application-for-development-with-docker-compose-on-ubuntu-18-04-ru|Контейнеризация приложения Laravel 6 для разработки с помощью Docker Compose в Ubuntu 18.04]]
 +
 +==== nodejs ====
 +Сборка в каталоге, лежащем на хосте
 +<code bash>
 +docker run --rm -w /home/node -v ./source:/home/node node:16 npm run build
 +</code>
 +
 +Сложный и неэффективный вариант (пока не понял, что можно проще).\\
 +Интересный приём - heredoc для ''docker build''.
 +<code bash>
 +workdir=/home/node
 +imagename=front:temp
 +
 +docker build -t $imagename -f - . << EOF
 +FROM node:16
 +WORKDIR $workdir
 +COPY --chown=node:node source/ ./
 +USER node
 +# npm rebuild нужен для решения проблемы с правами cross-env: Permission denied
 +RUN npm rebuild && npm run build
 +EOF
 +
 +# Вытащить каталоги client и admin из образа с архивацией gzip
 +id=$(docker create $imagename)
 +for i in client admin
 +do
 +  docker cp $id:$workdir/$i - |gzip > result/$i.tar.gz
 +done
 +docker rm $id
 +</code>
 +==== Скачивание и пересылка образа в закрытый контур ====
 +В закрытом контуре интернета нет, поэтому на какой-то внешней машине:
 +<code bash>
 +docker pull tomcat:jre11
 +docker save tomcat:jre11 |gzip > tomcat_jre11.tar.gz
 +# Куски по 24 МБ, цифровые индексы, в конец добавить .tar.gz, входной файл, имя (префикс) выходных файлов
 +split -b 24M -d --additional-suffix=.tar.gz tomcat_jre11.tar.gz tomcat_jre11_
 +ll -h
 +-rw-rw-r--  1 user user  24M May 21 11:53 tomcat_jre11_00.tar.gz
 +-rw-rw-r--  1 user user  24M May 21 11:53 tomcat_jre11_01.tar.gz
 +-rw-rw-r--  1 user user  24M May 21 11:53 tomcat_jre11_02.tar.gz
 +-rw-rw-r--  1 user user  24M May 21 11:53 tomcat_jre11_03.tar.gz
 +-rw-rw-r--  1 user user 1.5M May 21 11:53 tomcat_jre11_04.tar.gz
 +-rw-rw-r--  1 user user  98M May 21 11:44 tomcat_jre11.tar.gz
 +</code>
 +Дальше вытаскивать архивы наружу и слать по почте вложением или ещё как-нибудь.\\
 +Выгрузка образов: https://docs.docker.com/reference/cli/docker/image/save/
 +
 +На целевом сервере: объединение частей и загрузка образа.
 +<code bash>
 +cat tomcat_jre11_* > tomcat_jre11.tar.gz
 +zcat tomcat_jre11.tar.gz |docker load
 +</code>
 +
 +==== Сохранение всех образов в архивы ====
 +<code bash>
 +backupdir=/tmp/docker_images_backup
 +
 +mkdir $backupdir
 +# Кроме образов с тэгами, начинающимися на host:port/, т. е., тэгированных для частных репозиториев
 +images=($(docker image ls | awk '!/REPOSITORY|<none>/ {print $1":"$2}' |egrep -v ^.*:[[:digit:]]*/))
 +#  Замена / на _ в именах архивов
 +for i in "${images[@]}" ; do docker save $i |gzip > $backupdir/${i//\//_}.tar.gz ; done
 +</code>
 +<code bash>
 +user@k3:~/dockerimages$ ll -h
 +total 3.6G
 +drwxrwxr-x  2 user user 4.0K May 31 14:40 ./
 +drwxr-x--- 23 user user 4.0K May 31 14:26 ../
 +-rw-rw-r--  1 user user  11M May 31 14:37 epoupon_fileshelter:latest.tar.gz
 +-rw-rw-r--  1 user user  19M May 31 14:37 f0rc3_gokapi:latest.tar.gz
 +-rw-rw-r--  1 user user 636M May 31 14:36 frooodle_s-pdf:latest.tar.gz
 +-rw-rw-r--  1 user user 330M May 31 14:39 gradle:7.3.3-jdk11-alpine.tar.gz
 +-rw-rw-r--  1 user user 286M May 31 14:41 maven:3.5.2.tar.gz
 +-rw-rw-r--  1 user user  53M May 31 14:35 minio_minio:latest.tar.gz
 +-rw-rw-r--  1 user user 143M May 31 14:34 mirror.gcr.io_library_postgres:latest.tar.gz
 +-rw-rw-r--  1 user user  18M May 31 14:37 mtlynch_picoshare:latest.tar.gz
 +-rw-rw-r--  1 user user 324M May 31 14:33 nexus_nexus:latest.tar.gz
 +-rw-rw-r--  1 user user 487M May 31 14:40 nikosch86_onionshare:latest.tar.gz
 +-rw-rw-r--  1 user user 316M May 31 14:38 openjdk:11.tar.gz
 +-rw-rw-r--  1 user user 182M May 31 14:39 openjdk:17-alpine.tar.gz
 +-rw-rw-r--  1 user user 129M May 31 14:37 postgres:15.0.tar.gz
 +-rw-rw-r--  1 user user  75M May 31 14:36 psitrax_psitransfer:latest.tar.gz
 +-rw-rw-r--  1 user user 324M May 31 14:34 sonatype_nexus3:latest.tar.gz
 +-rw-rw-r--  1 user user 137M May 31 14:37 stonith404_pingvin-share:latest.tar.gz
 +-rw-rw-r--  1 user user  98M May 31 14:35 tomcat:9-jre11.tar.gz
 +-rw-rw-r--  1 user user  98M May 31 14:34 tomcat:jre11.tar.gz
 +</code>
 +
 +==== Загрузка всех образов из архивов ====
 +<code bash>
 +for i in $(ls *.tar.gz); do zcat $i |docker load; done
 +</code>
 +
 +==== Убрать повторяющиеся куски кода из docker-compose.yml ====
 +Называется "compose file extensions". Пишется код, ему присваивается якорь, а потом на него идёт ссылка.\\
 +''version:'' должна быть ''3.4'' и новее. Механизм негибкий, дочернюю строку в алиас не добавишь.
 +
 +<code yaml>
 +version: '3.7'
 +
 +x-fluentd: &fluentd
 +  driver: fluentd
 +  options: &fluentdopts
 +    fluentd-async-connect: 1
 +
 +services:
 +  nodeinfo:
 +    image: nodeinfo
 +    logging:
 +      <<: *fluentd
 +      options:
 +        <<: *fluentdopts
 +        tag: "nodeinfo"
 +</code>
 +
 +https://docs.docker.com/compose/compose-file/11-extension/\\
 +https://stackoverflow.com/questions/39731125/can-i-concatenate-aliases-in-yaml
 +
 +==== Сделать сеть с другим именем, не прописывая её явно для всех сервисов ====
 +Все сервисы стандартно ссылаются на сеть default, а тут ей задано другое имя. В результате будет сеть elastic, но прописывать её в сервисы не надо.
 +<code yaml>
 +networks:
 +  default:
 +    name: elastic
 +    external: false
 +</code>
 +https://github.com/elkninja/elastic-stack-docker-part-one/blob/main/docker-compose.yml
 +
 +==== Настроить контейнер с часовым поясом и временем, как у хоста ====
 +<code yaml>
 +volumes:
 +  - /etc/timezone:/etc/timezone:ro
 +  - /etc/localtime:/etc/localtime:ro
 +</code>
 +https://stackoverflow.com/questions/57607381/how-do-i-change-timezone-in-a-docker-container
service/docker.txt · Последнее изменение: viacheslav

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki