Различия
Показаны различия между двумя версиями страницы.
Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
system:docker [2018/06/23 04:18] – [Образы] mirocow | system:docker [2025/01/22 18:24] (текущий) – 192.168.1.104 | ||
---|---|---|---|
Строка 1: | Строка 1: | ||
- | {{tag> | + | {{tag> |
====== Docker ====== | ====== Docker ====== | ||
Строка 5: | Строка 5: | ||
{{https:// | {{https:// | ||
- | | VIRTUAL MACHINES | ||
- | | {{https:// | ||
- | | Virtual machines include the application, | ||
- | ===== Установка ===== | + | ====== Установка |
- | * https:// | + | ===== Ubuntu ===== |
- | nano /etc/apt/sources.list | + | <code bash> |
- | < | + | $ apt update && \ |
- | deb https:// | + | apt install ca-certificates curl gnupg lsb-release -y && \ |
+ | mkdir -p /etc/apt/keyrings && \ | ||
+ | curl -fsSL https:// | ||
+ | echo "deb [arch=$(dpkg --print-architecture) signed-by=/ | ||
+ | apt update && \ | ||
+ | apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin | ||
</ | </ | ||
+ | |||
+ | ===== Debian ===== | ||
<code bash> | <code bash> | ||
- | $ apt autoremove | + | $ apt update && \ |
- | $ apt install | + | apt install ca-certificates curl gnupg lsb-release |
- | $ docker run hello-world | + | mkdir -p / |
- | $ cd ./project/ | + | curl -fsSL https:// |
- | $ docker-compose | + | echo "deb [arch=$(dpkg --print-architecture) signed-by=/ |
+ | apt update && \ | ||
+ | apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin | ||
</ | </ | ||
- | * Запуск производится от root | + | ====== Docker ====== |
- | * [[system: | + | |
- | * [[system: | + | |
- | * [[system: | + | |
- | * [[system: | + | |
- | + | ||
- | === Запуск от пользователя | + | |
<code bash> | <code bash> | ||
$ sudo groupadd docker | $ sudo groupadd docker | ||
- | $ sudo gpasswd | + | $ sudo usermod |
- | $ sudo service | + | $ newgrp |
</ | </ | ||
- | ==== Mac OS ==== | ||
- | <code bash> | + | ====== UI ====== |
- | $ brew install docker docker-machine docker-compose docker-machine-driver-xhyve | + | |
- | </ | + | |
- | Подробнее: | + | |
- | ==== Установить последнюю версию | + | |
- | <note tip>< | + | * https:// |
- | $ curl -L "https:// | + | * https://github.com/felixgborrego/ |
- | $ chmod +x /usr/local/bin/docker-compose | + | * https://github.com/docker/kitematic |
- | </code> | + | * https://github.com/bcicen/ctop |
- | Работает с docker-compose.yml файлом< | + | |
- | Подробнее: | + | |
- | Пример: | + | |
- | ===== Настройка ===== | + | ===== Использование |
+ | |||
+ | * [[Dockerfile]] | ||
+ | * [[docker-compose.yml]] | ||
- | ==== Dockerfile | + | ==== Работа с образами / Images |
- | * FROM — указывает название образа (image), который будет взят за основу. | ||
- | * ENV — устанавливает переменную среды | ||
- | * RUN — запустить команду в контейнере (все команды исполняются с полными правами в пределах контейнера) | ||
- | * ADD — добавить файл в контейнер | ||
- | * VOLUME — указать монтируемые директории (их можно монтировать на хост машину или на другие контейнеры) | ||
- | * EXPOSE — указать транслируемые порты (их можно транслировать на хост машину или на другие контейнеры) | ||
- | * CMD — запустить процесс (это и будет процесс, | ||
- | * [[system: | + | <note important> |
- | * [[system: | + | $ docker |
- | ==== docker-compose ==== | + | </ |
- | * docker-compose - средство сборки и настройки | + | === Вывести список образов |
- | * docker-compose up - поднять контейнеры с учетом правил сборки docker-compose.yml | + | |
- | * -d - Для | + | |
<code bash> | <code bash> | ||
- | $ docker-compose config | + | $ docker |
- | $ docker-compose up | + | REPOSITORY |
+ | yii2_php | ||
</ | </ | ||
- | Отдельно стоит запомнить | + | === Удалить образ |
- | Сборочные контейнеры в связке с docker-compose удобно использовать в окружении разработчика, | + | <code bash> |
+ | $ docker | ||
+ | </ | ||
- | <note tip>С docker-compose все просто, | + | === Удалить все образы |
- | === Рабочий процесс === | + | <code bash> |
+ | $ sudo docker rm -f $(sudo docker ps -a -q) | ||
+ | $ sudo docker rmi -f $(sudo docker images -q) | ||
+ | </ | ||
- | Определение Dockerfile для каждого из сервисов | + | === Анализировать образ === |
- | Определение связей между сервисами при помощи [[system: | + | |
- | Запус системы при помощи docker-compose up | + | |
- | == Документация == | + | <code bash> |
- | + | $ docker image inspect 6a950c96e01d | |
- | * https:// | + | [ |
- | + | { | |
- | ==== docker-compose-mixer ==== | + | " |
- | + | " | |
- | Содержание конфигурационного docker-compose-mixer.yml файла по своей сути является небольшим конфигом, который описывает как именно два или более проектов будут стартовать вместе. | + | " |
- | + | ], | |
- | <note tip>< | + | " |
- | $ wget https:// | + | " |
- | $ chmod +x / | + | ... |
+ | } | ||
</ | </ | ||
- | Работает с docker-compose-mixer.yml файлом</ | ||
- | Решает проблемы: | + | === Избавляемся от неиспользуемых образов === |
- | * Конфликты имен контейнеров c обновлением всего дерева конфигурации | + | <code bash>$ docker image prune</ |
- | * Конфликты портов пробрасываемых на хост-машину | + | |
- | * Переопределение свойств сервиса | + | |
- | * Разрешение относительных путей | + | |
- | * Удаление лишних или дублирующихся сервисов | + | |
- | Подробнее: https:// | + | === Список образов === |
- | ==== docker-machine ==== | + | <note tip> |
- | В GitHub-репозитории Docker Machine можно найти три bash-сценария, | ||
- | |||
- | === Использование === | ||
- | |||
- | == создания нового хоста == | ||
- | |||
- | <code bash>$ docker-machine create --driver virtualbox machine-name</ | ||
- | |||
- | * -d --driver задаёт драйвер ([[https:// | ||
- | * generic | ||
- | * [[https:// | ||
- | * virtualbox | ||
- | * [[https:// | ||
- | |||
- | **generic** | ||
<code bash> | <code bash> | ||
- | $ docker-machine create \ | + | $ docker |
- | | + | REPOSITORY |
- | | + | yii2_php |
- | | + | yii2_nginx |
- | | + | yii2_kibana |
+ | yii2_elasticsearch | ||
+ | yii2_redis | ||
+ | yii2_mariadb | ||
</ | </ | ||
- | * где machine-name - название | + | === Получение образов === |
- | == запустить == | + | <note tip> |
+ | $ docker save vorobev4/ | ||
+ | </ | ||
- | <code bash>$ docker-machine start machine-name</ | + | === Установка образа === |
- | == выполнение команд на удаленном хосте == | + | <note tip> |
+ | $ docker load / | ||
+ | </ | ||
- | <code bash>$ docker-machine ssh machine-name cat /etc/ | + | ==== Работа с контейнерами |
- | или подключится к удаленному хосту | + | <note important> |
+ | $ docker | ||
+ | $ docker exec --help | ||
+ | </ | ||
- | <code bash>$ docker-machine ssh machine-name</ | + | === Запуск контейнера === |
- | == просмотреть список доступных | + | <note important> |
- | <code bash>$ docker-machine ls</ | + | <code bash>$ docker |
- | == получить | + | === Список запущеных контейнеров === |
- | <code bash>$ docker-machine inspect machine-name</ | + | <code bash> |
+ | $ docker | ||
+ | CONTAINER ID IMAGE COMMAND | ||
+ | a50423920e0d | ||
+ | fa24abd60049 | ||
+ | </ | ||
- | == настройки | + | === Подсоеденение к контейнеру === |
- | <code bash>$ docker-machine config machine-name</code> | + | <note tip>Проверить предварительно на наличие запрашиваемой оболочки. В alpine по умолчанию нет bash</note> |
- | == отображает IP-адрес хоста == | + | <code bash> |
+ | $ sudo docker exec -i -t a50423920e0d /bin/bash | ||
+ | $ sudo docker exec -i -t a50423920e0d /bin/sh | ||
+ | </ | ||
- | <code bash>$ docker-machine ip machine-name</ | + | ==== Запустить контейнер ==== |
- | == отключение == | + | <code bash>$ docker start a50423920e0d</ |
- | <code bash>$ docker-machine stop machine-name</ | + | ==== Остановить контейнер ==== |
- | == удаление == | + | <code bash>$ docker stop a50423920e0d</ |
- | <code bash>$ docker-machine rm machine-name</ | + | ==== Пребить контейнер ==== |
- | == список удаленных хостов == | + | <code bash>$ docker kill a50423920e0d</ |
- | <code bash> | + | ===== Использование |
- | === Сценарии === | + | <note important> |
+ | $ docker-compose | ||
+ | $ docker-compose exec | ||
+ | </ | ||
- | == 1 Сценарий | + | <hidden docker-composer.yml> |
+ | <code yaml> | ||
+ | version: ' | ||
+ | services: | ||
+ | mariadb: | ||
+ | build: ./ | ||
+ | restart: always | ||
+ | environment: | ||
+ | MYSQL_ROOT_PASSWORD: | ||
+ | MYSQL_DATABASE: | ||
+ | MYSQL_USER: skringo | ||
+ | MYSQL_PASSWORD: | ||
+ | ports: | ||
+ | - ' | ||
+ | expose: | ||
+ | - ' | ||
+ | volumes: | ||
+ | - ' | ||
+ | redis: | ||
+ | build: ./ | ||
+ | restart: always | ||
+ | environment: | ||
+ | - REDIS_VERSION=4.0.9 | ||
+ | ports: | ||
+ | - ' | ||
+ | expose: | ||
+ | - ' | ||
+ | redis-commander: | ||
+ | container_name: | ||
+ | hostname: redis-commander | ||
+ | image: rediscommander/ | ||
+ | build: . | ||
+ | restart: always | ||
+ | environment: | ||
+ | - REDIS_HOSTS=local: | ||
+ | ports: | ||
+ | - 8081:8081 | ||
+ | nginx: | ||
+ | build: ./ | ||
+ | restart: always | ||
+ | links: | ||
+ | - php | ||
+ | volumes: | ||
+ | - ' | ||
+ | - ' | ||
+ | - ' | ||
+ | environment: | ||
+ | - NGINX_VERSION=1.13.12-1~stretch | ||
+ | - NGINX_HOST=skringo.loc | ||
+ | - NGINX_PORT=80 | ||
+ | ports: | ||
+ | - ' | ||
+ | command: 'sh -c " | ||
+ | elasticsearch: | ||
+ | build: ./ | ||
+ | restart: always | ||
+ | ports: | ||
+ | - ' | ||
+ | expose: | ||
+ | - ' | ||
+ | environment: | ||
+ | - ELASTICSEARCH_VERSION=5.6.9 | ||
+ | - JAVA_ALPINE_VERSION=8.151.12-r0 | ||
+ | - JAVA_VERSION=8u151 | ||
+ | - LANG=C.UTF-8 | ||
+ | - cluster.name=docker-cluster | ||
+ | - bootstrap.memory_lock=true | ||
+ | - " | ||
+ | ulimits: | ||
+ | memlock: | ||
+ | soft: -1 | ||
+ | hard: -1 | ||
+ | mem_limit: 1g | ||
+ | kibana: | ||
+ | build: ./ | ||
+ | links: | ||
+ | - elasticsearch | ||
+ | ports: | ||
+ | - ' | ||
+ | php: | ||
+ | build: ./ | ||
+ | restart: always | ||
+ | links: | ||
+ | - mariadb | ||
+ | - redis | ||
+ | - elasticsearch | ||
+ | ports: | ||
+ | - ' | ||
+ | expose: | ||
+ | - ' | ||
+ | - ' | ||
+ | environment: | ||
+ | - PHP_IDE_CONFIG=serverName=skringo.loc | ||
+ | volumes: | ||
+ | - ' | ||
+ | - ' | ||
+ | - ' | ||
+ | - ' | ||
- | < | + | networks: |
+ | default: | ||
+ | external: | ||
+ | name: nginx-proxy | ||
+ | </code> | ||
+ | </hidden> | ||
- | Чтобы завершить установку этого файла, нужно | + | ==== Подсоеденение |
- | < | + | < |
+ | Где php название используемого сервиса / services | ||
- | Этот файл содержит три строки, которые | + | ==== Запуск |
- | < | + | < |
- | PS1=' | + | |
- | PS1=" | + | |
- | В конец каждой строки нужно вставить < | + | ==== Сети |
- | < | + | === Сетевые драйверы === |
- | PS1=' | + | |
- | PS1=" | + | |
- | Теперь имя | + | **bridge**: сетевой драйвер по умолчанию. |
+ | Если вы не указываете | ||
+ | Мостовые сети обычно используются, когда ваши приложения работают в автономных | ||
- | == 2 Сценарий | + | **host**: для автономных контейнеров, удаляет сетевую |
+ | Хост доступен только для служб swarm в Docker версии 17.06 и выше. | ||
- | Второй сценарий называется docker-machine-wrapper.bash. Он добавляет к команде docker-machine | + | **overlay**: |
+ | Вы также можете использовать overlay сети для | ||
+ | Или между двумя автономными контейнерами | ||
+ | Эта стратегия | ||
- | <code bash>$ wget https:// | + | **macvlan**: сети Macvlan позволяют назначать MAC-адрес контейнеру, |
+ | Демон Docker направляет трафик в контейнеры по их MAC-адресам. | ||
+ | Использование драйвера macvlan иногда является лучшим выбором при работе с устаревшими приложениями. | ||
+ | Приложениям, | ||
- | == 3 Сценарий | + | **none**: для этого контейнера отключит все сети. |
+ | Обычно используется в сочетании с пользовательским сетевым драйвером. Ни один не доступен для swarm услуг | ||
- | Последний сценарий называется docker-machine.bash. Он отвечает за завершение команд docker-machine. | + | === Установка === |
- | + | ||
- | <code bash>$ wget https:// | + | |
- | + | ||
- | Чтобы активировать внесённые изменения, | + | |
- | ===== Контейнер ===== | + | |
- | + | ||
- | ==== О контейнере ==== | + | |
<code bash> | <code bash> | ||
- | $ docker | + | $ docker |
- | + | $ docker network create --driver=bridge bridge-network | |
- | Containers: 9 | + | $ docker network create -d overlay my-multihost-network |
- | Running: 6 | + | $ docker |
- | | + | $ docker network create --subnet 10.1.0.0/16 --gateway=10.1.0.1 --ip-range 10.1.4.0/24 --driver=bridge --label=host4networks brifge04 |
- | | + | $ docker network create nginx-proxy |
- | Images: 28 | + | |
- | Server Version: 1.12.5 | + | |
- | Storage Driver: aufs | + | |
- | Root Dir: /var/lib/docker/aufs | + | |
- | | + | |
- | Dirs: 90 | + | |
- | | + | |
- | Logging Driver: json-file | + | |
- | Cgroup Driver: cgroupfs | + | |
- | Plugins: | + | |
- | | + | |
- | | + | |
- | Swarm: inactive | + | |
- | Runtimes: runc | + | |
- | Default Runtime: runc | + | |
- | Security Options: seccomp | + | |
- | Kernel Version: 3.16.0-4-amd64 | + | |
- | Operating System: Debian GNU/Linux stretch/ | + | |
- | OSType: linux | + | |
- | Architecture: | + | |
- | CPUs: 2 | + | |
- | Total Memory: 7.8 GiB | + | |
- | Name: nas.ztc | + | |
- | ID: 6JPA: | + | |
- | Docker Root Dir: / | + | |
- | Debug Mode (client): false | + | |
- | Debug Mode (server): false | + | |
- | Registry: https:// | + | |
- | WARNING: No memory limit support | + | |
- | WARNING: No swap limit support | + | |
- | WARNING: No kernel memory limit support | + | |
- | WARNING: No oom kill disable support | + | |
- | WARNING: No cpu cfs quota support | + | |
- | WARNING: No cpu cfs period support | + | |
- | Insecure Registries: | + | |
- | 127.0.0.0/8 | + | |
</ | </ | ||
- | ==== Статус ==== | + | === Использование |
<code bash> | <code bash> | ||
- | $ docker | + | $ docker |
- | + | $ docker run -it --name=test_brifge04_2 --net brifge04 --ip=10.1.4.100 centos: | |
- | CONTAINER | + | |
- | c8d1eb7a8f7a | + | |
- | 271073504ac9 | + | |
- | 462c8942181f | + | |
- | 94e2422ce234 | + | |
- | 6a43329858d9 | + | |
- | 404d5b6bf024 | + | |
</ | </ | ||
- | ==== Работа с контейнером ==== | + | === Аанализ |
<code bash> | <code bash> | ||
- | $ docker | + | $ docker |
- | $ docker | + | $ docker |
+ | $ docker network ls | ||
</ | </ | ||
- | ==== Список контейнеров (запущенных и нет) | + | ====== Особенности работы с MAC OS ====== |
- | <code bash> | + | Все контейнеры в MAC OS находятся в виртуальной машине qcow2 и находятся по адресу |
- | $ docker ps -a | + | /Users/mirocow/Library/Containers/com.docker.docker/ |
- | CONTAINER ID IMAGE | + | |
- | c8d1eb7a8f7a | + | |
- | 271073504ac9 | + | |
- | 462c8942181f | + | |
- | 94e2422ce234 | + | |
- | 6a43329858d9 | + | |
- | 404d5b6bf024 | + | |
- | </ | + | |
- | * -a - Позволяет увидеть не запущенные контейнеры | + | * где mirocow |
- | * -l - Выведет список недавно созданных контейнеров | + | |
- | * где docker-grand-ambassador | + | |
- | * curl -L http:// | + | |
- | ==== Остановка контейнера ==== | + | <note tip> |
+ | **screen ~/ | ||
- | < | + | ====== Автоматический запуск контейнеров в Debian ====== |
- | $ docker stop 7d0eb5cd3b3b | + | |
- | </ | + | |
- | ==== Удаление контейнера | + | ===== System V ===== |
+ | nano / | ||
<code bash> | <code bash> | ||
- | $ docker rm 7d0eb5cd3b3b | + | #!/bin/sh |
- | </code> | + | |
- | ===== Образы ===== | + | ### BEGIN INIT INFO |
+ | # Provides: | ||
+ | # Required-Start: | ||
+ | # Required-Stop: | ||
+ | # Default-Start: | ||
+ | # Default-Stop: | ||
+ | # Short-Description: | ||
+ | ### END INIT INFO | ||
+ | set -e | ||
- | <note tip> | + | PROJECT_NAME=portainer |
- | ==== Поиск образов ==== | + | YAMLFILE=/var/lib/jenkins/workspace/ |
+ | OPTS="-f $YAMLFILE -p $PROJECT_NAME" | ||
+ | UPOPTS="-d --no-recreate --no-build --no-deps" | ||
- | <code bash>$ docker search alpine</code> | + | . /lib/ |
- | ==== Загрузка образа в систему ==== | + | case " |
+ | start) | ||
+ | log_daemon_msg " | ||
+ | docker-compose $OPTS up $UPOPTS | ||
+ | ;; | ||
- | <code bash> | + | stop) |
- | $ docker | + | |
- | $ docker pull alpine: | + | |
- | </ | + | ;; |
- | ==== Чистые образы ==== | + | |
- | * https:// | + | reload) |
- | * https:// | + | |
- | * https:// | + | |
+ | ;; | ||
- | ==== Готовые сервисы ==== | + | restart) |
+ | docker-compose $OPTS stop | ||
+ | docker-compose $OPTS up $UPOPTS | ||
+ | ;; | ||
- | * https:// | + | status) |
- | * https:// | + | |
- | * https:// | + | if [ ! -z " |
- | * https:// | + | echo " |
- | * https:// | + | fi |
- | * https:// | + | ;; |
- | * https:// | + | |
- | * https:// | + | |
- | * https:// | + | |
- | * https:// | + | |
- | ==== Готовые сборки ==== | + | *) |
+ | log_action_msg " | ||
+ | exit 1 | ||
+ | ;; | ||
+ | esac | ||
- | * https:// | + | exit 0 |
- | * https:// | + | |
- | * https:// | + | |
- | * https:// | + | |
- | * https:// | + | |
- | ==== Создание образа ==== | + | |
- | + | ||
- | <code bash> | + | |
- | $ docker build -t image-name . | + | |
</ | </ | ||
- | * Где . папка, где расположен Dockerfile | + | ===== System D ===== |
- | * container-name - название создаваемого контейнера | + | |
- | ==== Вывод списка образов ==== | ||
+ | nano / | ||
<code bash> | <code bash> | ||
- | $ docker | + | [Unit] |
- | </ | + | Description=Portainer service with docker-compose |
+ | Requires=docker.service | ||
+ | After=docker.service | ||
- | ==== Запуск образа ==== | + | [Service] |
+ | Restart=always | ||
- | <code bash> | + | WorkingDirectory=/ |
- | $ docker run -d -p 80:80 -t image-name | + | |
- | $ docker run -d --publish 8080:80 -t image-name | + | |
- | </code> | + | |
- | * 8080 - Порт хост машины | + | # Remove old containers, network and volumes |
- | * 80 - Порт контейнера | + | ExecStartPre=/ |
- | | + | ExecStartPre=-/ |
- | | + | ExecStartPre=-/ |
+ | # Compose up | ||
+ | ExecStart=/ | ||
- | ===== Пример управления контейнером из другого контейнера ===== | + | # Compose down, remove containers |
- | + | ExecStop=/usr/ | |
- | <code bash>$ docker run -v /var/ | + | |
- | -v $(which docker):/ | + | |
- | -ti nachine_name</ | + | |
- | + | ||
- | ===== Пространства ===== | + | |
- | + | ||
- | Применяется для монтирования пространств из внешних источников. К примеру virtualbox | + | |
- | + | ||
- | * https:// | + | |
- | + | ||
- | ===== Сетевые драйверы ===== | + | |
- | + | ||
- | * https:// | + | |
- | + | ||
- | ===== Логирование ===== | + | |
- | + | ||
- | * https:// | + | |
- | + | ||
- | ====== Рецепты ====== | + | |
- | + | ||
- | * [[system: | + | |
- | * https:// | + | |
- | * https://github.com/trntv/yii2-starter-kit | + | |
- | * https://github.com/ | + | |
- | * https:// | + | |
+ | [Install] | ||
+ | WantedBy=multi-user.target | ||
+ | </ | ||
====== Проблемы и их решения ====== | ====== Проблемы и их решения ====== | ||
- | ===== Circular import between fpm and nginx ===== | + | ==== Circular import between fpm and nginx ==== |
Возникает при циклическом связывании контейнеров (2-ух сторонее связывание) | Возникает при циклическом связывании контейнеров (2-ух сторонее связывание) | ||
Строка 438: | Строка 469: | ||
</ | </ | ||
- | ===== ERROR: Couldn' | + | ==== ERROR: Couldn' |
скорее всего вам потребуется сделать следующее: | скорее всего вам потребуется сделать следующее: | ||
<code bash>$ docker-machine create --driver=xhyve dev --xhyve-experimental-nfs-share</ | <code bash>$ docker-machine create --driver=xhyve dev --xhyve-experimental-nfs-share</ | ||
+ | |||
====== Компоненты ====== | ====== Компоненты ====== | ||
* [[https:// | * [[https:// | ||
+ | * [[https:// | ||
* [[https:// | * [[https:// | ||
* [[https:// | * [[https:// | ||
Строка 450: | Строка 483: | ||
* [[https:// | * [[https:// | ||
* [[https:// | * [[https:// | ||
+ | * [[https:// | ||
+ | |||
+ | ====== Репозитории ====== | ||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
====== Документация / Статьи ====== | ====== Документация / Статьи ====== | ||
+ | * [[system: | ||
+ | * http:// | ||
* [[https:// | * [[https:// | ||
* [[http:// | * [[http:// | ||
Строка 471: | Строка 516: | ||
* https:// | * https:// | ||
* https:// | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
- | ====== | + | ====== |
- | {{topic> | + | {{topic> |