Linux
curl -sSL https://get.docker.com/ | sh
Mac
Скачайте dmg по этой ссылке:
https://download.docker.com/mac/stable/Docker.dmg
Windows
Используйте MSI-инсталлятор:
https://download.docker.com/win/stable/InstallDocker.msi
Работающие контейнеры
docker ps
docker ps -a
Логи контейнера
docker logs infinite
Информация о контейнере
docker inspect infinite
docker inspect --format '{{ .NetworkSettings.IPAddress }}' $(docker ps -q)
События контейнера
docker events infinite
Публичные порты
docker port infinite
Выполняющиеся процессы
docker top infinite
Использование ресурсов
docker stats infinite
Изменения в файлах или директориях файловой системы контейнера
docker diff infinite
Управление образами
Список образов
docker images
Создание образов
docker build .
docker build github.com/creack/docker-firefox
docker build - < Dockerfile
docker build - < context.tar.gz
docker build -t eon/infinite .
docker build -f myOtherDockerfile .
curl example.com/remote/Dockerfile | docker build -f - .
Удаление образа
docker rmi nginx
Загрузка репозитория в tar (из файла или стандартного ввода)
docker load < ubuntu.tar.gz
docker load --input ubuntu.tar
Сохранение образа в tar-архив
docker save busybox > ubuntu.tar
Просмотр истории образа
docker history
Создание образа из контейнера
docker commit nginx
Тегирование образа
docker tag nginx eon01/nginx
Push (загрузка в реестр) образа
docker push eon01/nginx
Сеть
Создание сети
docker network create -d overlay MyOverlayNetwork
docker network create -d bridge MyBridgeNetwork
docker network create -d overlay \ --subnet=192.168.0.0/16 \ --subnet=192.170.0.0/16 \ --gateway=192.168.0.100 \ --gateway=192.170.0.100 \ --ip-range=192.168.1.0/24 \ --aux-address="my-router=192.168.1.5" --aux-address="my-switch=192.168.1.6" \ --aux-address="my-printer=192.170.1.5" --aux-address="my-nas=192.170.1.6" \ MyOverlayNetwork
Удаление сети
docker network rm MyOverlayNetwork
Список сетей
docker network ls
Получение информации о сети
docker network inspect MyOverlayNetwork
Подключение работающего контейнера к сети
docker network connect MyOverlayNetwork nginx
Подключение контейнера к сети при его запуске
docker run -it -d --network=MyOverlayNetwork nginx
Отключение контейнера от сети
docker network disconnect MyOverlayNetwork nginx
Очистка Docker
Удаление работающего контейнера
docker rm nginx
Удаление контейнера и его тома (volume)
docker rm -v nginx
Удаление всех контейнеров со статусом exited
docker rm $(docker ps -a -f status=exited -q)
Удаление всех остановленных контейнеров
docker container prune
docker rm `docker ps -a -q`
Удаление контейнеров, остановленных более суток назад
docker container prune --filter "until=24h"
Удаление образа
docker rmi nginx
Удаление неиспользуемых (dangling) образов
docker image prune
docker rmi $(docker images -f dangling=true -q)
Удаление неиспользуемых (dangling) образов даже с тегами
docker image prune -a
Удаление всех образов
docker rmi $(docker images -a -q)
Удаление всех образов без тегов
docker rmi -f $(docker images | grep "^<none>" | awk "{print $3}")
Остановка и удаление всех контейнеров
docker stop $(docker ps -a -q) && docker rm $(docker ps -a -q)
Удаление неиспользуемых (dangling) томов
docker volume prune
docker volume rm $(docker volume ls -f dangling=true -q)
Удаление неиспользуемых (dangling) томов по фильтру
docker volume prune --filter "label!=keep"
Удаление неиспользуемых сетей
docker network prune
Удаление всех неиспользуемых объектов
docker system prune
По умолчанию для Docker 17.06.1+ тома не удаляются. Чтобы удалились и они тоже:
docker system prune --volumes
Docker Swarm
Установка Docker Swarm
curl -ssl https://get.docker.com | bash
Прим. перев.: в Docker версий 1.12.0+ ничего дополнительно устанавливать не требуется, т.к. Docker Swarm встроен в Docker Engine в виде специального режима (Swarm mode).
Инициализация Swarm
docker swarm init --advertise-addr 192.168.10.1
Подключение рабочего узла (worker) к Swarm
docker swarm join-token worker
Подключение управляющего узла (manager) к Swarm
docker swarm join-token manager
Список сервисов
docker service ls
Список узлов
docker node ls
Создание сервиса
docker service create --name vote -p 8080:80 instavote/vote
Список заданий Swarm
docker service ps
Масштабирование сервиса
docker service scale vote=3
Обновление сервиса
docker service update --image instavote/vote:movies vote
docker service update --force --update-parallelism 1 --update-delay 30s nginx
docker service update --update-parallelism 5--update-delay 2s --image instavote/vote:indent vote
docker service update --limit-cpu 2 nginx
docker service update --replicas=5 nginx
P.S.
Прим. перев.: Напомню, что оригинальная (англоязычная) версия Docker Cheat Sheet доступна и обновляется в Git-репозитории. Автор будет рад исправлениям/пополнениям от сообщества.
Читайте также в нашем блоге:
«Play with Docker — онлайн-сервис для практического знакомства с Docker».
«В чём суть проекта Moby и почему главным репозиторием Docker вдруг стал moby/moby?»
«Собираем Docker-образы для CI/CD быстро и удобно вместе с dapp (обзор и видео)».
Открыть файл configuration.sh в текстовом редакторе.
Настройка ссылок
Для запуска Cytomine необходимо настроить ссылки:
CORE_URL ссылка на основной Cytomine сервер.
IMS_URL ссылка на сервер изображений.
UPLOAD_URL ссылка для загрузки новых изображений.
CORE_URL, IMS_URL и UPLOAD_URL эти ссылки ДОЛЖНЫ быть разными доменами. Как пример, cytomine.domain.my и cytomine.domain.my/ims не будет работать, т.к. это один домен, зато cytomine.domain.my, cytomine-ims.domain.my, ... являются правильными ссылками.
Организуйте доступность установленной системы:
Для организации общего доступа, создайте DNS записи и сделайте доступными порты HTTP(S) (80/443) для адресов ваших хостов. Обычно это делают администраторы.
переменные $CORE_URL, $IMS_URL and $UPLOAD_URL должны быть заменены на ваши значения. Для локальной установки, откройте файл /etc/hosts в текстовом редакторе и добавьте например такие записи:
127.0.0.1 localhost-core
127.0.0.1 localhost-ims1
127.0.0.1 localhost-ims2
127.0.0.1 localhost-upload
127.0.0.1 rabbitmq
В Mac OS, запустите run sudo killall -HUP mDNSResponder после изменения /etc/hosts update.
Настройка путей на диске
Все пути указанные в файле конфигурации в разделе PATH должны существовать, в нашем случае должны быть проброшены
из Докера.
Другие настройки
О других настройках можно почитать по этой ссылке.
3. Запуск Cytomine
Для инициализации вашего конфигурационного файла. Запустите:
bash init.sh
Затем запустите запуск Cytomine
sudo bash start_deploy.sh
В первый запуск будет произведено скачивание необходимых компонентов, это может занять значительное время, всё зависит от скорости соединения.
4. Первый запуск
Для входа в Cytomine необходимо в браузере набрать ссылку, которая была указана в переменной CORE_URL (в примере localhost-core). По-умолчанию в системе создана учетная запись admin . Пароль к этому аккаунту генерируется случайным образом. Посмотреть сгенерированный пароль администратора можно в файле configs/core/cytomineconfig.groovy для этого можно набрать команду:
FROM (SELECT *,array_to_string(indkey,' ') AS cols FROM pg_index) a
JOIN (SELECT *,array_to_string(indkey,' ') as cols FROM pg_index) b ON (a.indrelid=b.indrelid AND a.indexrelid > b.indexrelid AND (
(a.cols LIKE b.cols||'%' AND COALESCE(substr(a.cols,length(b.cols)+1,1),' ')=' ') OR
(b.cols LIKE a.cols||'%' AND COALESCE(substr(b.cols,length(a.cols)+1,1),' ')=' ')
ORDER BY indrelid
Анализ индексов
SELECT s.relname AS tname, s.indexrelname as iname, s.idx_scan as used, pg_size_pretty(pg_relation_size(s.relid)) AS tsize, pg_size_pretty(pg_relation_size(s.indexrelid)) as isize, t.n_tup_upd+t.n_tup_ins+t.n_tup_del as writes, i.indexdef as create FROM pg_stat_user_indexes AS s
JOIN pg_indexes i ON (i.indexname=s.indexrelname AND s.schemaname=i.schemaname)
JOIN pg_stat_user_tables t ON t.relid=s.relid WHERE s.idx_scan<200 AND i.indexdef !~* 'unique'
ORDER BY s.relname, s.indexrelname
Создать таблицу на основе запроса
CREATE TABLE public.spsall AS SELECT a."ге_ключ",a.sps FROM public.allu a
Запрос из соседней БД
CREATE EXTENSION dblink;
SELECT max(l.date_edit) FROM
dblink('hostaddr=127.0.0.1 dbname=flats user=postgres password=postgresselect date_edit from public.logdata') as l(date_edit timestamp)
Список таблиц и полей
SELECT * FROM information_schema.tables WHERE table_schema='public'
Резервное копирование
SET PGPASSWORD=ПАРОЛЬ
pg_dump93.exe -i -h АДРЕС -p ПОРТ -U ПОЛЬЗОВАТЕЛЬ -F c -b -v -f ПУТЬ БАЗА
Настройка состояния сервера PGAdmin в файле конфигурации postgresql.conf найти lc_messages и прописать :
lc_messages = 'UTF-8'
Создание таблицы на основании запроса
CREATE TABLE public.table AS SELECT a.id FROM public.user u WHERE u.on=TRUE
Экспорт информации в файл CSV
COPY (SELECT * FROM people) TO 'ФАЙЛ' ENCODING 'Win1251' DELIMITER ';' CSV HEADER
Импорт информации в файл CSV
COPY ТАБЛИЦА(ПОЛЕ,ПОЛЕ) FROM 'ФАЙЛ' ENCODING 'Win1251' DELIMITER ';' CSV HEADER
Удаление дубликатов (поле ctid имеется во всех строках всех таблиц)
DELETE FROM table WHERE ctid NOT IN
(SELECT max(ctid) FROM table GROUP BY table.*)
Вставка данных из запроса
INSERT INTO ТАБЛИЦА1(ПОЛЕ,ПОЛЕ) SELECT ПОЛЕ,ПОЛЕ FROM ТАБЛИЦА2
Генератор последних четвергов месяца
SELECT (
date trunc('month',d)-interval '1 day' -
(case EXTRACT(DOW FROM date_trunc('month',d)-interval '1 day') when 0 then 3
when 6 then 2
when 5 then 1
when 3 then 6
when 2 then 5
when 1 then 4
else 0
end)*interval '1 day'
)::DATE as last_thesday_in_month FROM
generate_series('01.11.2019'::date,'01.01.2022'::date,interval '1 month') as d ORDER BY 1
Обновление полей из подзапроса
UPDATE accounts SET (contact_first_name, contact_.last_name) = (SELECT first_name, last_name FROM salesmen WHERE salesmen.id = accounts.sales_id);
или
UPDATE accounts SET pontact_first_name = first_name, contact_last_name = last_name FROM salesmen WHERE salesmen.id = accounts.sales id;
Пересечение диапазонов
SELECT * FROM table
WHERE (start1,end1) OVERLAPS (start2,end2)
Рекурсивный запрос
WITH RECURSIVE chtopar AS (
SELECT d.id, d.parent_ref, d.department_sh, 1 as level
FROM staff.departments d
WHERE d.id = 1
UNION ALL
SELECT d.id, d.parent_ref, d.department_sh, c.level+1 as level
FROM staff.departments d
JOIN chtopar c
ON d.parent_ref = c.id
)
SELECT * FROM chtopar;
Работа с массивами
Содержимое массива
SELECT ARRAY[1,4,3] @> ARRAY[3,1] --содержатся ли элементы второго массива в первом
SELECT ARRAY[3,1] <@ ARRAY[1,4,3] --содержатся ли элементы первого массива во втором
Для начала определим, что такое система контроля версий.
Так называют программу, которая позволяет хранить разные версии одного и того же документа, легко переключаться между ранними и поздними вариантами, вносить и отслеживать изменения.
Систем контроля версий много и все они работают по принципу компьютерной игры, где вы можете вернуться к месту сохранения, если что-то пошло не так.
Одна из самых популярных систем называется Git. Её отличие от других программ — отсутствие графической версии. Поэтому работа с Git ведётся через командную строку. В разных операционных системах свои программы для взаимодействия с Git.
В Windows их две: PowerShell и cmd.exe. В Ubuntu это Terminal. Самая популярная программа на macOS тоже называется Terminal. Если вам не подходит встроенная в систему программа для работы с командной строкой, вы можете поставить свою. Например, написанную на JavaScript программу Hyper, которая работает на любой операционной системе. На Windows популярны программы Cmder и Git Bash, а на macOS — iTerm.
В мире разработки такие программы называют «терминал» или «консоль». А работает это так: мы вводим команду и получаем реакцию машины: сообщение об ошибке, запрос на подтверждение информации, результат выполненных действий.
Git — важный навык веб-разработчика
А лучший способ научиться программировать — профессия «React-разработчик». В программе три интенсива, прокачка навыков и оплачиваемая стажировка.
Устанавливаем Git
Если раньше вы не работали с Git, сперва его нужно установить. Способы зависят от операционной системы вашего компьютера.
Установка в Windows
Скачайте exe-файл инсталлятора с сайта Git и запустите его. Это Git для Windows, он называется msysGit. Установщик спросит добавлять ли в меню проводника возможность запуска файлов с помощью Git Bash (консольная версия) и GUI (графическая версия). Подтвердите действие, чтобы далее вести работу через консоль в Git Bash. Остальные пункты можно оставить по умолчанию.
Установка на macOS
Скачиваем Git со страницы проекта.
Запускаем загруженный файл.
Система может показать окно с ошибкой, где будет написано, что файл скачан с неавторизованного сайта и инсталлятор не может быть запущен. В таком случае нужно зайти в «Системные настройки» — «Безопасность» (Security and Privacy), в появившемся окне будет сообщение об ошибке и кнопка Open anyway (Всё равно открыть). Нажимаем.
Система покажет окно, уточняющее хотите ли вы запустить установку. Подтверждаем действие.
Установщик проведёт через все необходимые шаги.
Установка в Linux
Используйте обычный менеджер пакетов вашего дистрибутива. Откройте терминал и введите подходящие команды.
Если у вас 21 или более ранняя версия Fedora, используйте yum install git.
Для 22 и последующих версий Fedora вводите dnf install git.
Для дистрибутивов, основанных на Debian, например, Ubuntu, используйте apt-get: sudo apt-get install git.
Полный список команд для различных дистрибутивов можно посмотреть здесь.
Проверим, что Git установлен
После того, как все действия по установке завершены, убедимся, что Git появился в системе компьютера. Откройте терминал и введите git --version, должна появиться текущая версия программы на вашей машине. Эта проверка подходит для всех операционных систем.
Настройка Git
После того как Git появился на компьютере, нужно ввести свои данные, а именно имя и адрес электронной почты. Ваши действия в Git будут содержать эту информацию.
Откройте терминал и используйте следующую команду, чтобы добавить своё имя: git config --global user.name "ваше имя"
Для добавления почтового адреса вводите: git config --global user.email адрес
Обратите внимание, что в командах, указанных выше, есть опция --global. Это значит, что такие данные будут сохранены для всех ваших действий в Git и вводить их больше не надо. Если вы хотите менять эту информацию для разных проектов, то в директории проекта вводите эти же команды, только без опции --global.
Регистрация на GitHub
Что такое GitHub?
GitHub — веб-сервис, который основан на системе Git. Это такая социальная сеть для разработчиков, которая помогает удобно вести коллективную разработку IT-проектов. Здесь можно публиковать и редактировать свой код, комментировать чужие наработки, следить за новостями других пользователей. Именно в GitHub работаем мы, команда Академии, и студенты интенсивов.
Чтобы начать работу с GitHub, нужно зарегистрироваться на сайте, если вы ещё этого не сделали. За дело.
Переходим на сайт GitHub.
Для начала регистрации:
Третий шаг — небольшой опрос от GitHub, который вы можете пройти, заполнив все поля и нажать Submit или пропустить, нажав skip this step.
После прохождения всех этапов на сайте, на указанный при регистрации ящик вам придёт письмо от GitHub. Откройте его и подтвердите свой почтовый адрес, нажав Verify email address (подтвердить электронный адрес) или скопируйте вспомогательную ссылку из письма и вставьте её в адресную строку браузера.
После верификации GitHub предложит создать новый репозиторий, организацию или узнать больше о GitHub. Этот пункт пока можно пропустить и перейти в профиль.
Нажимаем кнопку Sign up (зарегистрироваться), попадаем на страницу регистрации, где вводим обязательные данные: имя пользователя, адрес электронной почты и пароль. После заполнения полей проходим верификацию.
После заполнения данных и успешного прохождения верификации нажимаем на кнопку Select a plan.
Теперь у вас есть профиль на GitHub.
Устанавливаем SSH-ключи
Git установлен, профиль на GitHub создан. Осталось добавить SSH-ключ и можно приступать к работе с проектом.
Что такое SSH-ключ и зачем он нужен?
Чтобы работать со своего компьютера с GitHub, иметь доступ к проектам, хранящимся на сервисе, выполнять команды в консоли без постоянного подтверждения пароля, нужно пройти авторизацию у сервера. В этом помогают SSH-ключи.
Каждый SSH-ключ содержит пару: открытый (публичный) и закрытый (приватный) ключ. Открытый ключ отправляется на сервер, его можно не прятать от всех и не переживать, что кто-то его увидит и украдёт. Он бесполезен без своей пары — закрытого ключа. А вот закрытый ключ — секретная часть. Доступ к нему должен быть только у вас.
Вы отправляете какую-то информацию на сервер, где хранится ваш публичный ключ, сервер понимает, что вы это вы, то есть идентифицирует именно вас, и даёт вам какой-то ответ. И только вы можете расшифровать этот ответ, потому что только у вас есть подходящий закрытый ключ. Получается что-то вроде связки логин-пароль только намного безопасней. Ваш пароль кто-то может узнать или подобрать, а чтобы получить ваш приватный SSH-ключ, злоумышленнику придётся взломать ваш компьютер.
Чтобы пройти авторизацию по SSH-ключу, его надо сгенерировать или найти уже ранее созданный ключ на своём компьютере.
Сначала проверим, есть ли уже на компьютере ключ. По умолчанию SSH-ключи хранятся в каталоге ~/.ssh, поэтому нужно проверить содержимое этого каталога.
1. Открываем консоль.
2. Вводим
cd ~/.ssh
, чтобы перейти в нужный каталог.
Используем
ls
, чтобы увидеть список всех файлов в каталоге.
Ищем пару файлов с названиями вида имя и имя.pub. Обычно имя — id_rsa, id_dsa, id_ecdsa или id_ed25519. Файл с расширением .pub — ваш публичный ключ, а второй — ваш приватный, секретный ключ. Если таких файлов или даже каталога .ssh у вас нет, вы можете их сгенерировать. Для этого делаем следующее.
Указываем тот адрес электронной почты, который вводили при регистрации на GitHub.
- Далее нужно указать расположение файла для сохранения ключа. Если вы не введёте путь до файла и просто нажмёте Enter, ключ сохранится в файле, указанном в скобках.
- Теперь нужно установить пароль к вашему ключу и дважды ввести его. Если вы не хотите вводить пароль каждый раз, когда используете ключ, пропустите этот шаг, нажав «Enter», и ничего не вводите.
4. Добавляем ключ в
ssh-agent
(сгенерированный или уже существующий). Проверяем доступность ключа командой
eval "$(ssh-agent -s)"
и добавляем с помощью
ssh-add ~/.ssh/your_key_name
, где указываем верный путь до файла с ключом и его имя.
Несколько важных примечаний:
- Если вы захотите переименовать ключ, могут возникнуть проблемы. Их можно решить, добавив в ~/.ssh/config связь ключа с доменом.
- Если у вас Windows и вы пользуетесь программой Cmder, возможны проблемы с командой eval "$(ssh-agent -s)". Может появиться такое сообщение об ошибке: «eval не является внутренней или внешней командой, исполняемой программой или пакетным файлом».
Если проблема осталась, рекомендуем работать в Git Bash
- Если у вас macOS Sierra версии 10.12.2 и выше, нужно изменить ваш ~/.ssh/config файл, чтобы автоматически загрузить ключи в ssh-agent и хранить пароли.
. Если у вашего ключа другое имя, не забудьте заменить
id_rsa
в команде на правильное название.
- Если у вас Linux, может понадобится переназначить для ~/.ssh права доступа командой chmod 700 ~/.ssh/
5. После того как создан ключ, его нужно добавить на GitHub. Для этого копируем его содержимое с помощью одной из следующих команд:
Если вы на Windows clip .
Для пользователей macOS pbcopy .
На Linux используйте sudo apt-get install xclip, чтобы установить необходимый для копирования пакет xclip, а затем введите xclip -sel clip . Или введите команду cat ~/.ssh/id_rsa.pub, контент документа появится прямо в консоли и вы сможете скопировать ключ оттуда.
6. Переходим на страницу для работы с ключами в вашем профиле на GitHub.
Нажимаем кнопку New SSH key (новый SSH-ключ). Вводим имя ключа (можно придумать абсолютно любое) в поле Title (название), а в Key (ключ) вставляем сам ключ из буфера обмена. Теперь нажимаем Add SSH key (добавить SSH-ключ).
Если всё сделано верно, в списке появится новый ключ.
Теперь, наконец-то, мы можем начать работу с самим проектом.
Работа с репозиториями
Для начала определим, что такое репозиторий
.
Это рабочая директория с вашим проектом. По сути, это та же папка с HTML, CSS, JavaScript и прочими файлами, что хранится у вас на компьютере, но находится на сервере GitHub. Поэтому вы можете работать с проектом удалённо на любой машине, не переживая, что какие-то из ваших файлов потеряются — все данные будут в репозитории при условии, что вы их туда отправите. Но об этом позже.
Если над проектом трудится команда разработчиков, как правило, создаётся общий репозиторий, в котором находится рабочая версия проекта (назовём его мастер-репозиторий). При этом каждый пользователь клонирует себе в профиль оригинальный репозиторий и работает именно с копией. Такая копия называется форком. Так как форк — ваша персональная версия мастер-репозитория, в нём вы можете пробовать разные решения, менять код и не бояться что-то сломать в основной версии проекта.
Как сделать форк мастер-репозитория?
Заходим в нужный репозиторий, нажимаем на «вилку» с надписью fork. Форк репозитория создан и находится в вашем профиле на GitHub.
Теперь нужно склонировать форк себе на компьютер, чтобы вести работу с кодом локально. Тут нам и пригодится SSH.
Открываем консоль, переходим в директорию, где хотим сохранить папку с проектом, и вводим команду:
Если вы правильно настроили SSH-ключи, Git начнёт процесс копирования репозитория на ваш компьютер. Если вы видите ошибку, в которой написано Error: Permission denied (publickey), скорее всего, вы ошиблись где-то при выполнении инструкции по настройке SSH-ключа. Вернитесь на несколько абзацев ранее и попробуйте повторить процесс настройки.
Если вы не хотите вручную вводить адрес репозитория, вы можете зайти на страницу проекта, нажать зелёную кнопку Clone or download (клонировать или скачать), выбрать Clone with SSH (клонировать по SSH) и скопировать адрес, который находится в текстовом поле. Этот адрес вы можете вставить в команду git clone.
Кстати, если вы хотите, чтобы название папки с проектом у вас на компьютере отличалось от имени репозитория, можете дополнить команду клонирования, добавив в конце другое название:
Теперь, на вашем компьютере, в папке your_project или в той, название которой вы указали самостоятельно, находится полная копия репозитория c GitHub.
Чтобы начать работу с проектом, надо оказаться в его директории. Для этого используем команду cd, после которой указываем название проекта на вашем компьютере: cd your-project
Работу над проектом принято вести в ветках. В каждом репозитории есть как минимум одна ветка. Это основная ветка, которую создаёт сам Git, она называется master . Обычно в ней находится стабильная версия программы без ошибок. Если вы хотите исправить баг, добавить новую функциональность в проект, попробовать какую-то технологию, но не хотите сломать код в основной ветке, вы ответвляетесь из master и трудитесь в своей новой ветке. Здесь вы можете реализовывать свои идеи, не переживая, что рабочий код сломается. Каждая ветка — что-то вроде второстепенной дороги, которая затем снова соединяется с основной.
Создадим новую ветку. Открываем терминал, вводим команду git branch. Она показывает список веток, с которыми мы работаем в проекте, и выделяет текущую. Если мы находимся в master создаём новую ветку: git checkout -b имя-новой-ветки.
Если текущая ветка не master, сначала переключимся в основную ветку: git checkout master. Мы делаем это, чтобы новая ветка содержала свежую, на момент создания, рабочую версию проекта.
Эта команда позволяет переключаться между существующими ветками в проекте, после git checkout надо указать название нужной ветки.
Если вы ошиблись в названии, например, допустили опечатку, вы можете изменить название ветки с помощью команды: git branch -m старое-имя-ветки новое-имя-ветки.
После того как вы создали ветку, поработали в ней у себя локально — нужно сохранить результат, чтобы он не пропал и в итоге оказался в репозитории.
Если вы хотите сохранить изменения не во всех файлах, для начала можно ввести команду git status. Она покажет текущее состояние в вашей ветке, а именно список с названиями изменённых файлов, если они есть, и укажет на те, которые ожидают записи и сохранения (обычно они выделены красным цветом).
Перед тем, как зафиксировать изменения отдельных файлов, нужно добавить файлы в набор этих изменений. Воспользуйтесь командой git add имя-файла. Если название очень длинное, вы можете начать его писать, затем нажать Tab и консоль сама предложит вам продолжение пути к файлу.
Если вы хотите сохранить все изменения разом, вводите git add -A.
Теперь мы можем сделать коммит, то есть зафиксировать все сохранённые изменения и дать им название. Это делается с помощью команды git commit -m "ваше сообщение". Текст сообщения должен быть лаконичным и в то же время сообщать о том, что делает коммит (внесённые изменения). Например, «добавляет имя наставника в Readme», «вводит функцию сортировки изображений», «правит ошибку в поиске городов на карте».
Сохранения зафиксированы, всё? Они теперь в репозитории и видны коллегам? Пока нет. Те изменения, которые мы внесли и сохранили, пока локальны. Их нужно послать на GitHub.
Чтобы отправить свои изменения (коммиты) в репозиторий на GitHub, введите команду git push origin название-текущей-ветки, где origin означает репозиторий, который был склонирован на компьютер, то есть ваш форк.
Теперь заходим на страницу нашего форка и создаём пулреквест, чтобы слить свой код с данными в мастер-репозитории. Что такое пулреквест? Это предложение изменить код в репозитории.
Любое предложение можно принять или отвергнуть. Так же и с пулреквестом. После его создания, он должен получить ревью и одобрение так называемого коллаборатора — пользователя GitHub, который имеет права администратора в мастер-репозитории. Им может быть ваш коллега-разработчик, техлид, наставник. Если к вашему коду нет вопросов, пулреквест принимается и изменения из вашей ветки попадают в master главного репозитория. Если в код нужно внести изменения, пулреквест отклоняется, и вам нужно снова пройти по цепочке локальные изменения — сохранение — коммит — пуш, только пулреквест заново делать не нужно. Если вы продолжаете вести работу в той же ветке и пулреквест ещё не принят, все ваши изменения автоматически добавятся в пулреквест, созданный из этой ветки после команды git push origin название-текущей-ветки.
Вы исправили код, наставник или техлид одобрил ваши правки и принял пулреквест. Теперь код в мастер-репозитории обновился, а в вашем форке нет, вы ведь не обновляли свою версию репозитория с тех пор, как клонировали её себе на компьютер. Приведём форк в актуальное состояние.
1. В локальном репозитории вводим команду git checkout master, переходим в master.
2. Теперь забираем (подтягиваем) изменения из ветки master мастер-репозитория git pull academy master. Academy здесь — сокращённое название мастер-репозитория, такое имя используется в проектах студентов Академии, вы можете выбрать любое другое название.
Если консоль выдаёт ошибку и говорит, что не знает директории с таким именем, нужно добавить ссылку на этот репозиторий:
Появилась необходимость сделать лог файл наблюдения доступности узла сети. Для этой цели вполне подходит команда ping. Но для того чтобы со строкой доступности узла было указано время поможет следующий скрипт:
ping 8.8.8.8 | while read pong; do echo "$(date): $pong"; done
Для того, чтобы включить .htaccess в Apache2, надо отредактировать всего-лишь один файл. Этот файл лежит в /etc/apache2/sites-available и называется default или другой конфигурационный.
и исправляем:
AllowOverride None
на
AllowOverride All
2. Создаем файл .htaccess
# Кодировка сайта:
AddDefaultCharset UTF-8
# Запрет на отображение содержимого каталога при отсутствии индексного файла(например, index.html)
Options -Indexes
# Правило для url
# Включаем модуль RewriteEngine для создания единой точки входа RewriteEngine On
# Правила для шаблон MVC
# Чтобы не обрабатывать файлом index.php графические файлы, css.
# js файлы, а позволять их скачивать браузеру на прямую
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Перенаправлять все запросы на index.php
RewriteRule $ index.php [nocase,last]
После обновления Composer выдает Deprecation Notice
Ошибка
Deprecation Notice: Composer\Package\Version\VersionParser::parseLinks is deprecated.
Use \Composer\Package\Loader\ArrayLoader::parseLinks() instead in phar:///home/user/site.ru/composer.phar/src/Composer/Package/Version/VersionParser.php:226
Решение (12:00 29 июля) 10:00 30 июля. Обновился плагин до 1.0.3, достаточно обновить плагин в режиме global:
php composer.phar global require "fxp/composer-asset-plugin:~1.0"
Старое решение
1. удаляем lock файл в папке проекта и папке global (~/.composer папка в корне с общими настройками composer) и папку vendor (можно просто её переименовать)
2. Чистим кэш
php composer.phar clear-cache
3. Обновляем плагин до версии "dev-master" (скоро добавят тэг https://github.com/francoispluchino/composer-asset...):
/opt/php5.6/bin/php -d memory_limit=-1 composer.phar global require "fxp/composer-asset-plugin:dev-master"
## или без лишних флагов:
php composer.phar global require "fxp/composer-asset-plugin:dev-master"
обязательно global require, тк при установке yii2 мы устанавливаем этот плагин как раз с global.
Ключ -y для apt-get за вас отвечает согласием на установку и обновление пакетов.
Связка && между командами, запускает следующую, если предыдущая отработала без ошибок.
Для обеспечения элементарной безопасности (чтобы не забрутфорсили) я вам рекомендую сменить сразу дефолтный адрес phpMyAdmin. Для этого редактируйте файл:
sudo nano /etc/apache2/conf-enabled/phpmyadmin.conf
В нём строку:
Alias /phpmyadmin /usr/share/phpmyadmin
Замените на:
Alias /secret /usr/share/phpmyadmin
Сохраните файл (в nano для этого достаточно нажать F2) и перезапустите Apache:
sudo service apache2 restart
Теперь phpMyAdmin будет доступен по ссылке http://127.0.0.1/secret (где 127.0.0.1 — IP вашего сервера)
Сегодня я расскажу вам, как с помощью JavaScript и d3 нарисовать карту, подобную моей.
Утилиты (Prerequisites)
Для начала работы нам понадобятся две утилиты ogr2ogr и topojson. ogr2ogr входит в состав GDAL — библиотеки и набора утилит для работы с гео‑данными. topojson — небольшая утилита, написанная на JavaScript и работающая на node.js.
Установить GDAL (и, соответственно, ogr2ogr)
Под Linux тоже есть соответствующий пакет:
sudo apt-get install gdal-bin
Далее необходимо установить node.js:
sudo apt-get install nodejs
Устанавливаем npm:
sudo apt-get install npm
Вторая утилита ставится через npm :
sudo npm install -g topojson
Всё, теперь можно приступать к работе.
Данные
Вся суть любой карты — это данные. Не будет данных, нечего будет рисовать. Я рекомендую данные Natural Earth из‑за их доступности и открытости. Итак, идём в раздел 1:10m, Cultural и скачиваем карту с делением по странам (первый раздел, Admin 0 — Countries, любая ссылка).
Скачали, распаковали. Теперь с этим добром нужно что‑то делать, данные‑то в формате Shapefile. Для преобразования данных в читаемый вид нам и понадобится ogr2ogr — утилита, которая преобразует данные из одного векторного формата в другой. У неё огромное количество различных параметров, но я облегчу вам задачу.
После вызова этой команды должен появиться файл countries.json, содержащий те же данные, но в формате GeoJSON. Размер файла, конечно, не маленький — 24 Мб. Но не стоит отчаиваться: для работы понадобится его более оптимизированный собрат — TopoJSON.
topojson -o world.json countries.json
Если во время выполнения скрипта выпало сообщение:
/usr/bin/env: node: Нет такого файла или каталога
или
/usr/bin/env: node: No such file or directory
Это связано с тем что некоторые дистрибутивы линукс включают node.js под именем nodejs. Поэтому нужно создать сначала создать ссылку:
ln -s /usr/bin/nodejs /usr/bin/node
После снова попробовать переконвертировать файл. В результате имеем файл размером 2.3 Мб, с ним и будем работать. Этот размер можно ещё значительно уменьшить, но об этом я расскажу чуть позже.
Первая картинка
Начнём с создания новой страницы:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Map Tutorial 01</title> <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/3.0.1/normalize.min.css"/> <script src="http://d3js.org/d3.v3.min.js"></script> <script src="http://d3js.org/topojson.v1.min.js"></script> </head> <body> <script> // Здесь будет код </script> </body> </html>
Теперь можно открывать всё это в браузере. Подойдёт любой статический сервер. Например, в PhpStorm, который я использую, можно просто нажать на файл правой клавишей и выбрать «Открыть в браузере» — выбранный файл отобразится с помощью небольшого встроенного в IDE сервера.
Создаём элемент <svg> размером с окно, в котором и будет происходить вся отрисовка. Для этого заменяем комментарий на подходящий код:
var width = window.innerWidth;
var height = window.innerHeight;
var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height);
Эта инструкция создаёт html‑элемент <svg>, добавляет его к <body> и прописывает подходящие размеры в атрибуты width и height.
Пришла пора загрузить данные. Дописываем в конец:
d3.json("/js/world.json", function (error, world) {
if (error) {
console.log(error);
return;
}
На самом деле это я быстро набросал, чтобы было что показать. Теперь будем постепенно менять, приводя к виду, который на самом деле хочется получить.
После каждого логического куска поста есть две ссылки: на результат, который должен был получиться, и на написанный мной код. Первые две можете наблюдать под картинкой чуть выше. Если вдруг что‑то не получается, всегда можно подсмотреть или даже скопировать мою версию.
Проекция
Пока не начинаешь рисовать карту, даже не задумываешься, какое огромное количество проекций придумали люди, чтобы покрасивее отобразить объёмную землю на плоской бумаге. Меркатор, Winkel Tripel, Aitoff, Dymaxion, проекция Гуда… Их десятки, если не сотни. В контексте d3 проекция — это просто функция, которая переводит географические координаты (широту и долготу) в координаты на экране.
На картинке выше используется Меркатор. Это можно увидеть и в коде.
Вынесем код создания проекции в самый верх и поместим проекцию в отдельную переменную, она нам ещё пригодится.
var projection = d3.geo.winkel3();
Код отрисовки карты чуть поменялся и стал ссылаться на новую переменную.
Как, может быть, вы уже заметили, я заменил Меркатора на более аккуратную Winkel Tripel (именно эту проекцию использует National Geographic для своих изданий). К сожалению, проекция не входит в стандартную поставку d3, поэтому придётся подключить ещё отдельный плагин с её определением.
Возвращаемся к данным. Помните, что мы преобразовали наши данные в компактный TopoJSON? Перед отрисовкой эти данные всё равно придётся преобразовать обратно в GeoJSON, для этого у нас и подключена библиотека TopoJSON, посмотрите в заголовке нашего html.
var countries = topojson.feature(world, world.objects.countries).features;
В переменной countries теперь содержится массив с описанием стран в формате GeoJSON. Нарисуем их с помощью раздельных элементов <path>, благо d3 позволяет сделать это быстро и просто.
Создаём группу (элемент <g>), которая очень пригодится нам в будущем. Это нужно вставить сразу после объявления переменной svg.
Если вы ещё не знаете, что делает enter c выборкой из selectAll, то быстренько сходите и восполните этот пробел.
Переменная path в последней строчке — это функция, которая переводит описание страны из GeoJSON в строку, подходящую для отображения в svg. Её можно объявить в самом верху, сразу после объявления проекции.
var path = d3.geo.path().projection(projection);
Обновляем страницу (Результат, Исходники). Теперь границы государств стали более различимыми. Сделаем их ещё более видимыми с помощью css. Добавим в заголовок страницы блок <style>:
Пришла пора добавить интерактива к карте. Но для начала разместим карту по центру и растянем на весь экран.
Для растягивания проекции нужно указать параметр scale, который по‑умолчанию равен 150. К сожалению, все соотношения меняются от проекции к проекции, поэтому просто посчитаем нужные параметры для нашей. Для этого в инспекторе браузера нужно глянуть ширину и высоту элемента path, соответствующего фону. В случае Winkel Triple ширина равна 772, а высота — 472.
Максимальное увеличение, при котором карта будет помещаться на экран, по горизонтали равно 150 / 772 * width, по вертикали — 150 / 472 * height. Выбираем меньшее из двух.
Всё, теперь можно добавлять интерактив. Как и положено, в таких библиотеках уже много всего придумано и реализовано за вас, остаётся только вызвать нужную функцию в нужный момент.
Создаём объект behavior.zoom, который будет отвечать за отслеживание событий:
var zoom = d3.behavior.zoom()
.scaleExtent([1, 60])
.size([width, height])
.on('zoom', onZoom);
Присоединяем созданный объект к нашему элементу <svg>:
function onZoom () { var t = d3.event.translate; var s = d3.event.scale; t[0] = Math.max(Math.min(t[0], 0), width * (1 - s)); t[1] = Math.max(Math.min(t[1], 0), height * (1 - s)); zoom.translate(t); g.style("stroke-width", 1 / s) .attr('transform', 'translate(' + t + ')scale(' + s + ')'); }
В d3 параметры события сохраняются в специальном объекте d3.event, в случае события zoom нас интересуют два параметра: translate — смещение карты и scale — текущее увеличение. После получения этих параметров мы накладываем ограничение на смещение, чтобы пользователь не мог сдвинуть карту дальше её границ. Затем мы записываем новое смещение обратно в объект zoom: без этого он будет продолжать считать, что текущее смещение другое и сообразно обрабатывать новые события от мыши. И последнее действие — применить новые параметры смещения и увеличения к карте: нужно же, чтобы картинка менялась соответственно нашим действиям.
Кстати, именно для правильной работы масштабирования мы и создавали элемент <g> выше. Атрибут transform не работает с элементом <svg>.
Результат, Исходники.
Дополнительные данные
Идём дальше. Добавим к нашей карте немножко больше данных. Я создавал карту посещённых стран и городов, о чём и буду рассказывать. Я думаю, некоторые идеи можно применить и для других целей и наборов данных.
Такие совсем специфические данные, как список посещённых стран, взять негде, их придётся создавать самостоятельно. Я для этих целей создал файл data.json в таком формате:
{ // Список стран "AUT": { // Код страны "name": "Австрия", // Название страны по-русски "color": "turquoise", // Цвет подсветки: blue, green, orange, pink, purple, red, turquoise, yellow "cities": [ // Список городов внутри страны { "name": "Вена", // Название города по-русски "lat": 48.216667, // Широта "lon": 16.373333 // Долгота }, { "name": "Грац", "lat": 47.066667, "lon": 15.433333 } ] }, ... }
Чтобы вам не заморачиваться с созданием собственного файла, я предлагаю пока воспользоваться моим, потом переделаете всё так, как нравится. Скачать файлик можно по этой ссылке.
Загружаем данные из data.json сразу после загрузки карты и добавляем правильный фон к странам.
var visitedData = {};
d3.json("world.json", function (error, world) {
if (error) {
console.log(error);
return;
}
d3.json("data.json", function (error, data) {
if (error) {
console.log(error);
} else {
visitedData = data;
}
var countries = topojson.feature(world, world.objects.countries).features;
g.selectAll('.country').data(countries).enter()
.append('path')
.attr('class', 'country')
.attr('d', path)
.style('fill', function (d) {
var color = visitedData[d.id] && visitedData[d.id].color;
return color && COLORS[color] || '#ffffdd';
});
});
});
В d3, если в методы attr и style вторым параметром передать функцию, то значения атрибутов и стилей соответственно будут браться из результатов вызова этой функции. Первым параметром передаётся значение элемента массива, ранее заданного с помощью метода data.
Остаётся добавить массив констант с вариантами цвета фона где‑нибудь в начале файла:
Запускаем и видим, что ничего не поменялось (Результат, Исходники). На самом деле причина проста: в файле world.json нет информации о кодах стран. Ошибка исправляется передачей дополнительного параметра в вызов topojson. Перегенерировать world.json нужно такой командой:
Теперь можно нарисовать города. Для этого сразу после кода, ответственного за рисование стран, добавляем код для рисования городов:
// Собираем все города в один массив. for (var i in visitedData) { if (visitedData.hasOwnProperty(i) && visitedData[i].cities) { cities.push.apply(cities, visitedData[i].cities); } } // Рисуем города g.selectAll('.city').data(cities).enter() .append('path') .attr('class', 'city') .attr('d', function (d) { return path({ 'type': 'Point', 'coordinates': [d.lon, d.lat] }); });
Обратите внимание, что координаты в path передаются в формате [широта, долгота].
Не забываем в начале объявить массив cities:
var cities = [];
И добавить стиль для городов:
.city { fill: #dd3d30; }
Смотрим результат:
Результат, Исходники
Да, точки для городов хотелось бы сделать поменьше. Добавляем правило рисования точек в path:
var path = d3.geo.path().projection(projection).pointRadius(1);
А ещё неплохо было бы сделать так, чтобы размер точек менялся с масштабом. Значит, добавляем код в конец функции onZoom.
Осталось написать обработчики событий мыши mousemove и mouseout. Для этого в операцию создания стран добавляем новые инструкции (новый код начинается с вызова метода on).
g.selectAll('.country').data(countries).enter() .append('path') .attr('class', 'country') .attr('d', path) .style('fill', function (d) { var color = visitedData[d.id] && visitedData[d.id].color; return color && COLORS[color] || '#ffffdd'; }) .on('mousemove', function (d) { var mouse = d3.mouse(svg.node()); var name = visitedData[d.id] && visitedData[d.id].name; if (!name) { return; } tooltip.style("display", "block") .style("left", mouse[0] + "px") .style("top", mouse[1] + "px") .html(name); }) .on('mouseout', function () { tooltip.style('display', 'none'); });
Из‑за того, что метод on вызван после вызова enter, события вешаются на каждый элемент <path> в отдельности, а в параметры передаётся соответствующий элемент из массива countries.
Метод d3.mouse возвращает текущие координаты мыши относительно контейнера, переданного в параметрах. В нашем случае это элемент <svg>. Дальше все просто: записываем в tooltip нужное содержимое и устанавливаем стили left, top и display.
В обработчике события mouseout прячем наш элемент с подписью. И всё работает как надо!
Добавим аналогичный код для отображения подписей к городам.
Некоторые из вас, должно быть, заметили, что, например, Франция имеет территорию в Южной Америке, которая тоже подсвечивается. А от этого хочется избавиться, ведь нас там не было. Чтобы получить правильный результат, можно воспользоваться другим набором данных с Natural Earth. Снова идём в раздел 1:10m, Cultural и скачиваем карту с делением по subunits (Admin 0 — Details, Download map subunits).
Если мы просто заменим файл с исходными данным, то быстро заметим, что кроме Франции изменениям подверглись ещё несколько стран. Например, Бельгия оказалась разделена на три части: Фландрию, Валлонию и Брюссель, да и на Великобритании тоже появились границы между Англией, Шотландией и Уэльсом. Получается, чтобы получить желаемый результат, придётся составить карту из двух источников.
Возьмём Францию из ne_10m_admin_0_map_subunits. Обратите внимание на параметр -where, который накладывает нужные ограничения на выборку.
Обратите внимание на то, как изменился вызов topojson, особенно параметр id-property. Все дело в том, что атрибут ADM_A3 содержит код страны, то есть у всех частей Франции код будет один и тот же. Поэтому для неё нужен другой атрибут в качестве идентификатора. Атрибуты в параметре id-property берутся в обратном порядке: сначала утилита пытается взять SU_A3, а в случае, если его нет, берет предыдущий, то есть ADM_A3.
Теперь для правильной отрисовки нужно добавить в массив countries новые элементы.
var countries = topojson.feature(world, world.objects.countries).features; countries.push.apply(countries, topojson.feature(world, world.objects.subunits).features);
Конструкция push.apply добавляет все элементы одного массива в другой. Более подробно про this, call и apply можно почитать в моей старой статье про ООП в JavaScript (раздел «Ключевое слово this»).
Осталось исправить в нашем файле с данными код Франции (новый код — «FXX») и наслаждаться результатом.
Результат, Исходники
Разбиение стран на регионы
Следующее пожелание: крупные страны, например, США и Россию, поделить на штаты и субъекты соответственно. Для этого нам понадобится новый источник данных. Снова идём на привычный адрес и скачиваем файл из раздела Admin 1 — States, Provinces.
Пересобираем файлы, не забыв предварительно удалить старые (org2org отказывается перезаписывать файлы, если вы ещё не заметили).
Так же как и раньше, добавляем новые данные для рисования в массив countries.
var countries = topojson.feature(world, world.objects.countries).features; countries.push.apply(countries, topojson.feature(world, world.objects.subunits).features); countries.push.apply(countries, topojson.feature(world, world.objects.regions).features);
Вообще говоря, подсветку штатов и субъектов я писал отдельно, но можно просто добавить нужные идентификаторы в файл data.json.
Результат, Исходники
Атрибуты
В файлах, скачанных с Natural Earth, есть множество дополнительных данных, не только форма границ и код страны. Большая часть этих данных лежит в файле .dbf, который представляет собой файл базы данных dBase. И если у вас есть просмотрщик для этого формата, то можете смело его открывать. Если же нет, то можно воспользоваться Online‑конвертером из dbf в csv. Я использовал именно этот способ. После конвертации сsv‑файл можно открыть LibreOffice или же Microsoft Excel.
ogr2ogr тоже копирует все данные из файлов атрибутов внутрь результирующего файла, а topojson может копировать некоторые необходимые атрибуты в файл TopoJSON. Вот таким образом можно добавить атрибут NAME, который содержит английское название объекта:
Теперь можно использовать значение поля, например, для отображения названий непосещённых стран. Вот эту строчку нужно заменить в обработчике события mousemove для стран:
var name = visitedData[d.id] && visitedData[d.id].name || d.properties.name || d.properties.NAME;
Результат, Исходники.
Уменьшение размера файла с картой
Последний нерешенный вопрос: размер файла с картой. После всех наших манипуляций он стал весить 2.6 Мб, что, согласитесь, несколько многовато. topojson предоставляет несколько параметров для оптимизации. Один из них так и называется — simplify. Для получения оптимального результата придётся, конечно, немного поэкспериментировать с величиной, в нашем же случае вполне подойдёт 1e-6.
Получившийся файл имеет размер 444 Кб и всё ещё приемлемую детализацию.
Результат, Исходники.
Благодарности
Спасибо Mike Bostock за такую прекрасную библиотеку. И отдельное спасибо ему же за прекрасные записи в блоге, некоторые идеи из которых перекочевали в этот пост.
Спасибо всем тем, кто дочитал до конца. Надеюсь, этот пост поможет вам.