Капитан грузового судна, или Как начать использовать Docker в своих проектах
Рассказываем, что такое Docker, как его использовать, а также пробежимся по сильным сторонам, терминологии и установке инструмента.
Docker является open source инструментом, который автоматизирует разворачивание приложения внутри программного контейнера. Мы перевели для вас руководство по работе с Docker для новичков.
Простейший способ понять идею Docker — это сравнить его с обычным контейнером для транспортировки. Когда-то давно компании, занимающиеся транспортировкой, столкнулись со следующими проблемами:
- Как перевозить разные (несовместимые) друг с другом типы грузов, например, еду и химикаты или стекло и кирпичи?
- Как работать с упаковками различных размеров, используя один и тот же транспорт?
С тех пор, как появились контейнеры, стало возможным помещать кирпичи поверх стекла, а химикаты — хранить рядом с едой. Груз различных размеров может быть помещен в стандартный контейнер, который загружен/разгружен одним и тем же транспортом.
Но вернемся к контейнерам в программной разработке.
Написанным кодом порою приходится делиться с другими людьми, например, разработчиками. Кроме того, в комплекте необходимо отправлять и все его зависимости вроде библиотек, веб-сервера, баз данных и так далее. Вы можете столкнуться с ситуацией, когда приложение работает на компьютере, но не может запуститься на тестовом сервере, компьютере разработчика или тестировщика.
В чем отличие от виртуализации?
Традиционно виртуальные машины используются, чтобы избежать неожиданного поведения. Главная проблема с ними заключается в том, что «дополнительная ОС» поверх основной ОС добавляет к проекту гигабайты места. Большую часть времени ваш сервер будет держать несколько виртуальных машин, что займет ещё больше пространства. Другой значительный недостаток — медленная загрузка.
Docker устраняет эти проблемы разделением ядра между всеми контейнерами, которые работают как отдельные процессы основной ОС.
Надо понимать, что Docker — не первая и не единственная платформа, основанная на контейнерах. Однако на данный момент он является самым большим и самым мощным инструментом на рынке.
Зачем нам нужен Docker?
Список преимуществ таков:
- Быстрый процесс разработки. Нет нужды в установке сторонних программ вроде PostgreSQL, Redis, Elasticsearch. Они могут быть запущены в контейнерах.
- Удобная инкапсуляция приложений. Вы можете предоставить свое приложение как единое целое.
- Одинаковое поведение на локальном компьютере и тестовом/производственном сервере.
- Простой и понятный мониторинг.
- Легко масштабируется. Если вы сделали свое приложение правильно, то оно будет готово к масштабированию не только в Docker.
Поддерживаемые платформы
Linux является нативной платформой Docker, так как последний основан на особенностях, предоставляемых ядром операционной системы. Несмотря на это, вы можете запустить его на macOS или Windows. Разница состоит лишь в том, что Docker на них инкапсулирован в маленькую виртуальную машину. В настоящий момент Docker для этих ОС достиг значительного уровня удобства использования и очень похож на нативное приложение.
Более того, есть много дополнительных приложений, таких как Kitematic или Docker Machine, которые помогут установить Docker и управлять им на отличных от Linux платформах.
Установка
Вы можете посмотреть инструкцию по установке на официальном сайте. Если вы запустили Docker на Linux, вам следует выполнить все последующие команды из-под root или добавить своего пользователя в группу docker и перелогиниться:
sudo usermod -aG docker $(whoami)
Терминология
- Контейнер — текущий экземпляр, который инкапсулирует необходимое ПО. Контейнеры всегда создаются из образов. Могут открывать порты и тома для взаимодействия с другими контейнерами и/или внешним миром, а также легко удаляются и пересоздаются заново за короткий промежуток времени.
- Образ — основной элемент для каждого контейнера. После его создания каждый шаг кэшируется и может быть использован повторно (модель копирования при записи). В зависимости от образа может понадобиться некоторое время для его построения. Из них могут быть сразу запущены контейнеры.
- Порт — TCP/UDP-порт в своем обычном представлении. Порты могут быть открыты для внешнего мира (доступы через основную ОС) или подсоединены к другим контейнерам — доступны только из тех контейнеров и невидимы для внешнего мира.
- Том — может быть описан как общая папка. Тома инициализируются при создании контейнера. Они спроектированы для хранения данных независимо от жизненного цикла контейнера.
- Реестр — сервер, который хранит образы Docker. Функционирует по аналогии с Github — можно вытянуть образ, чтобы развернуть его локально, а затем закинуть обратно в реестр.
- Docker Hub — реестр с веб-интерфейсом, созданный Docker Inc. Он хранит большое количество Docker-образов с разным ПО. Docker Hub является источником «официальных» Docker-образов, созданных командой Docker. Официальные образы содержат списки своих потенциальных уязвимостей. Эта информация доступна для каждого авторизированного пользователя. Доступны два типа аккаунтов: бесплатные и платные. На бесплатном аккаунте может быть один приватный образ и бесконечное количество общедоступных образов.
Пример 1: Hello world
Настало время запустить ваш первый контейнер:
docker run ubuntu /bin/echo 'Hello world'
Вывод консоли:
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
d54efb8db41d: Pull complete
f8b845f45a87: Pull complete
e8db7bf7c39f: Pull complete
9654c40e9079: Pull complete
6d9ef359eaaa: Pull complete
Digest: sha256:dd7808d8792c9841d0b460122f1acf0a2dd1f56404f8d1e56298048885e45535
Status: Downloaded newer image for ubuntu:latest
Hello world
- docker run — команда, запускающая контейнер.
- ubuntu — образ, который вы запускаете, например, образ ОС Ubuntu. Когда вы определяете его, Docker начинает поиск на Docker-хосте. Если образ не существует локально, тогда он будет вытянут из общественного реестра — Docker Hub.
- /bin/echo 'Hello world' — команда, которая будет запущена внутри нового контейнера. Данный контейнер просто выведет «Hello world» и остановит выполнение.
Давайте попробуем создать интерактивную оболочку внутри Docker-контейнера:
docker run -i -t –rm ubuntu /bin/bash
- -t — флаг, добавляющий псевдотерминал внутри нового контейнера.
- -i — флаг, который позволяет установить интерактивное соединение, взяв стандартный ввод (STDIN) контейнера.
- --rm — флаг, автоматически удаляющий контейнер после завершения процесса. По умолчанию контейнеры не удаляются. Этот контейнер существует, пока установлена текущая сессия оболочки, и уничтожается, когда мы покидаем сессию (например, SSH-сессию с удаленным сервером).
Если вы хотите оставить контейнер работающим после завершения сессии, превратите его в демон-процесс:
docker run –name daemon ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
- --name daemon — устанавливает имя демона для нового контейнера. Если вы не определите имя, то Docker сгенерирует и присвоит его автоматически.
- -d — флаг запускает контейнер в фоновом режиме (демонизирует его).
Давайте взглянем, какие контейнеры у нас есть на текущий момент:
docker ps -a
Вывод консоли:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1fc8cee64ec2 ubuntu "/bin/sh -c 'while..." 32 seconds ago Up 30 seconds daemon
c006f1a02edf ubuntu "/bin/echo 'Hello ..." About a minute ago Exited (0) About a minute ago gifted_nobel
- docker ps — команда для вывода списка контейнеров.
- -a — флаг, который показывает все контейнеры (без этого флага ps выведет только работающие контейнеры).
Команда ps показала, что у нас всего два контейнера:
- gifted_nobel (имя для этого контейнера сгенерировано автоматически, оно будет другим на вашем компьютере) — это первый контейнер, который мы создали, выводит один раз «Hello world».
- daemon — это третий контейнер, который мы создали, работает как фоновый процесс.
Замечание: здесь нет второго контейнера (с интерактивной оболочкой), потому что мы установили флаг --rm. Как следствие, этот контейнер автоматически удалился сразу после выполнения.
Давайте проверим логи и посмотрим, что фоновый контейнер делает прямо сейчас:
docker logs -f daemon
Вывод консоли:
. . .
hello world
hello world
hello world
- docker logs — объединяет логи контейнера.
- -f — флаг для слежения за выводом логов (работает так же, как tail -f).
Теперь остановим фоновый контейнер:
docker stop daemon
Удостоверимся, что контейнер остановился:
docker ps -a
Вывод консоли:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1fc8cee64ec2 ubuntu "/bin/sh -c 'while..." 5 minutes ago Exited (137) 5 seconds ago daemon
c006f1a02edf ubuntu "/bin/echo 'Hello ..." 6 minutes ago Exited (0) 6 minutes ago gifted_nobel
Контейнер остановился. Мы можем запустить его заново:
docker start daemon
Удостоверимся, что он работает:
docker ps -a
Вывод консоли:
ONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1fc8cee64ec2 ubuntu "/bin/sh -c 'while..." 5 minutes ago Up 3 seconds daemon
c006f1a02edf ubuntu "/bin/echo 'Hello ..." 6 minutes ago Exited (0) 7 minutes ago gifted_nobel
Теперь остановим его опять и удалим все контейнеры вручную:
docker stop daemon
docker rm
docker rm daemon
Чтобы удалить все контейнеры, мы можем использовать следующую команду:
docker rm -f $(docker ps -aq)
- docker rm — команда для удаления контейнера.
- -f — флаг для rm, который останавливает контейнер, если он работает (принудительное удаление).
- -q — флаг для ps, который выводит только ID контейнеров.
Пример 2: Nginx
Начиная с этого примера, вам понадобятся несколько дополнительных файлов, которые вы можете найти в Github-репозитории. Скачать файл можно, нажав на эту ссылку.
Настало время создать и запустить более полезный контейнер типа Nginx.
Сменим директорию на examples/nginx:
docker run -d --name test-nginx -p 80:80 -v $(pwd):/usr/share/nginx/html:ro nginx:latest
Вывод консоли:
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
693502eb7dfb: Pull complete
6decb850d2bc: Pull complete
c3e19f087ed6: Pull complete
Digest: sha256:52a189e49c0c797cfc5cbfe578c68c225d160fb13a42954144b29af3fe4fe335
Status: Downloaded newer image for nginx:latest
436a602273b0ca687c61cc843ab28163c720a1810b09005a36ea06f005b0c971
- -p — преобразование портов HOST PORT:CONTAINER PORT.
- -v — монтирование тома HOST DIRECTORY:CONTAINER DIRECTORY.
Важно: команда run принимает только абсолютные пути. В нашем примере мы использовали $(pwd), чтобы установить абсолютный путь текущей директории.
Теперь вы можете открыть localhost в вашем браузере.
Или можно изменить /example/nginx/index.html (который смонтирован как том в /usr/share/nginx/html внутри контейнера) и обновить страницу.
Получим информацию о контейнере test-nginx:
docker inspect test-nginx
Эта команда показывает широкую системную информацию об установке Docker. Эта информация включает в себя версию ядра, количество контейнеров и образов, открытые порты, смонтированные тома и так далее.
Пример 3: написание Dockerfile
Чтобы создать Docker-образ, вам необходимо создать Dockerfile. Это просто текстовый файл с инструкциями и аргументами. Вот описание инструкций, которые мы будем использовать в нашем следующем примере:
- FROM — устанавливает базовый образ.
- RUN — выполняет команду в контейнере.
- ENV — устанавливает переменную окружения.
- WORKDIR — устанавливает рабочую директорию.
- VOLUME — создает точку монтирования для тома.
- CMD — устанавливает исполняемый файл для контейнера.
Вы можете просмотреть справку по Dockerfile, чтобы узнать больше подробностей.
Теперь создадим образ, который будет получать содержимое сайта с помощью curl и записывать его в текстовый файл. Нам надо передать URL сайта через переменную окружения SITE_URL. Результирующий файл будет помещен в директорию, смонтированную в качестве тома:
FROM ubuntu:latest
RUN apt-get update
RUN apt-get install --no-install-recommends --no-install-suggests -y curl
ENV SITE_URL https://google.com/
WORKDIR /data
VOLUME /data
CMD sh -c "curl -L $SITE_URL > /data/results"
Dockerfile готов. Теперь настало время создать сам образ.
Перейдем в examples/curl и выполним следующую команду для создания образа:
docker build . -t test-curl
Вывод консоли:
Sending build context to Docker daemon 3.584 kB
Step 1/7 : FROM ubuntu:latest
---> 0ef2e08ed3fa
Step 2/7 : RUN apt-get update
---> Running in 4aa839bb46ec
Get:1 http://archive.ubuntu.com/ubuntu xenial InRelease [247 kB]
Get:2 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB]
...
Fetched 24.9 MB in 4s (5208 kB/s)
Reading package lists...
---> 35ac5017c794
Removing intermediate container 4aa839bb46ec
Step 3/7 : RUN apt-get install --no-install-recommends --no-install-suggests -y curl
---> Running in 3ca9384ecf8d
Reading package lists...
Building dependency tree...
Reading state information...
The following additional packages will be installed...
---> f3c6d26b95e6
Removing intermediate container 3ca9384ecf8d
Step 4/7 : ENV SITE_URL https://google.com/
---> Running in 21b0022b260f
---> 9a733ee39a46
Removing intermediate container 21b0022b260f
Step 5/7 : WORKDIR /data
---> c024301ddfb8
Removing intermediate container 3bc973e5584c
Step 6/7 : VOLUME /data
---> Running in a9594a8958fe
---> 6802707a7114
Removing intermediate container a9594a8958fe
Step 7/7 : CMD sh -c "curl -L $SITE_URL > /data/results"
---> Running in 37503bc4e386
---> 5ebb2a65d771
Removing intermediate container 37503bc4e386
Successfully built 5ebb2a65d771
- docker bulid — создает новый локальный образ.
- -t — устанавливает именную метку для образа.
Теперь у нас есть новый образ, и мы можем посмотреть список существующих:
docker images
Вывод консоли:
REPOSITORY TAG IMAGE ID CREATED SIZE
test-curl latest 5ebb2a65d771 37 minutes ago 180 MB
nginx latest 6b914bbcb89e 7 days ago 182 MB
ubuntu latest 0ef2e08ed3fa 8 days ago 130 MB
Мы можем создать и запустить контейнер из образа. Попробуем сделать это со стандартными параметрами:
docker run --rm -v $(pwd)/vol:/data/:rw test-curl
Чтобы увидеть результаты, сохраненные в файле, выполним команду:
cat ./vol/results
Попробуем с facebook.com:
docker run --rm -e SITE_URL=https://facebook.com/ -v $(pwd)/vol:/data/:rw test-curl
И снова посмотрим результаты:
cat ./vol/results
Пример 4: связь контейнеров Python + Redis
Docker compose — единственный правильный способ соединять контейнеры друг с другом. В этом примере мы соединим контейнеры Python и Redis:
version: '2'
services:
app:
build:
context: ./app
depends_on:
- redis
environment:
- REDIS_HOST=redis
ports:
- "5000:5000"
redis:
image: redis:3.2-alpine
volumes:
- redis_data:/data
volumes:
redis_data:
Go to example
Перейдем в examples/compose и выполним следующую команду:
docker-compose --project-name app-test -f docker-compose.yml up
Вывод консоли:
Creating network "apptest_default" with the default driver
Creating volume "apptest_redis_data" with default driver
Pulling redis (redis:3.2-alpine)...
3.2-alpine: Pulling from library/redis
627beaf3eaaf: Pull complete
a503a4771a4a: Pull complete
72c5d910c683: Pull complete
6aadd3a49c30: Pull complete
adf925aa1ad1: Pull complete
0565da0f872e: Pull complete
Digest: sha256:9cd405cd1ec1410eaab064a1383d0d8854d1eef74a54e1e4a92fb4ec7bdc3ee7
Status: Downloaded newer image for redis:3.2-alpine
Building app
Step 1/9 : FROM python:3.5.2-alpine
3.5.2-alpine: Pulling from library/python
b7f33cc0b48e: Pull complete
8eda8bb6fee4: Pull complete
4613e2ad30ef: Pull complete
f344c00ca799: Pull complete
Digest: sha256:8efcb12747ff958de32b32424813708f949c472ae48ca28691078475b3373e7c
Status: Downloaded newer image for python:3.5.2-alpine
---> e70a322afafb
Step 2/9 : ENV BIND_PORT 5000
---> Running in 8518936700b3
---> 0f652cdd2cee
Removing intermediate container 8518936700b3
Step 3/9 : ENV REDIS_HOST localhost
---> Running in 027286e90699
---> 6da3674f79fa
Removing intermediate container 027286e90699
Step 4/9 : ENV REDIS_PORT 6379
---> Running in 0ef17cb512ed
---> c4c514aa3008
Removing intermediate container 0ef17cb512ed
Step 5/9 : COPY ./requirements.txt /requirements.txt
---> fd523d64faae
Removing intermediate container 8c94c82e0aa8
Step 6/9 : COPY ./app.py /app.py
---> be61f59b3cd5
Removing intermediate container 93e38cd0b487
Step 7/9 : RUN pip install -r /requirements.txt
---> Running in 49aabce07bbd
Collecting flask==0.12 (from -r /requirements.txt (line 1))
Downloading Flask-0.12-py2.py3-none-any.whl (82kB)
Collecting redis==2.10.5 (from -r /requirements.txt (line 2))
Downloading redis-2.10.5-py2.py3-none-any.whl (60kB)
Collecting itsdangerous>=0.21 (from flask==0.12->-r /requirements.txt (line 1))
Downloading itsdangerous-0.24.tar.gz (46kB)
Collecting Werkzeug>=0.7 (from flask==0.12->-r /requirements.txt (line 1))
Downloading Werkzeug-0.11.15-py2.py3-none-any.whl (307kB)
Collecting Jinja2>=2.4 (from flask==0.12->-r /requirements.txt (line 1))
Downloading Jinja2-2.9.5-py2.py3-none-any.whl (340kB)
Collecting click>=2.0 (from flask==0.12->-r /requirements.txt (line 1))
Downloading click-6.7-py2.py3-none-any.whl (71kB)
Collecting MarkupSafe>=0.23 (from Jinja2>=2.4->flask==0.12->-r /requirements.txt (line 1))
Downloading MarkupSafe-1.0.tar.gz
Installing collected packages: itsdangerous, Werkzeug, MarkupSafe, Jinja2, click, flask, redis
Running setup.py install for itsdangerous: started
Running setup.py install for itsdangerous: finished with status 'done'
Running setup.py install for MarkupSafe: started
Running setup.py install for MarkupSafe: finished with status 'done'
Successfully installed Jinja2-2.9.5 MarkupSafe-1.0 Werkzeug-0.11.15 click-6.7 flask-0.12 itsdangerous-0.24 redis-2.10.5
---> 18c5d1bc8804
Removing intermediate container 49aabce07bbd
Step 8/9 : EXPOSE $BIND_PORT
---> Running in f277fa7dfcd5
---> 9f9bec2abf2e
Removing intermediate container f277fa7dfcd5
Step 9/9 : CMD python /app.py
---> Running in a2babc256093
---> 2dcc3b299859
Removing intermediate container a2babc256093
Successfully built 2dcc3b299859
WARNING: Image for service app was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating apptest_redis_1
Creating apptest_app_1
Attaching to apptest_redis_1, apptest_app_1
redis_1 | 1:C 08 Mar 09:56:55.765 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1 | _._
redis_1 | _.-``__ ''-._
redis_1 | _.-`` `. `_. ''-._ Redis 3.2.8 (00000000/0) 64 bit
redis_1 | .-`` .-```. ```\/ _.,_ ''-._
redis_1 | ( ' , .-` | `, ) Running in standalone mode
redis_1 | |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
redis_1 | | `-._ `._ / _.-' | PID: 1
redis_1 | `-._ `-._ `-./ _.-' _.-'
redis_1 | |`-._`-._ `-.__.-' _.-'_.-'|
redis_1 | | `-._`-._ _.-'_.-' | http://redis.io
redis_1 | `-._ `-._`-.__.-'_.-' _.-'
redis_1 | |`-._`-._ `-.__.-' _.-'_.-'|
redis_1 | | `-._`-._ _.-'_.-' |
redis_1 | `-._ `-._`-.__.-'_.-' _.-'
redis_1 | `-._ `-.__.-' _.-'
redis_1 | `-._ _.-'
redis_1 | `-.__.-'
redis_1 |
redis_1 | 1:M 08 Mar 09:56:55.767 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1 | 1:M 08 Mar 09:56:55.767 # Server started, Redis version 3.2.8
redis_1 | 1:M 08 Mar 09:56:55.767 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis_1 | 1:M 08 Mar 09:56:55.767 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
redis_1 | 1:M 08 Mar 09:56:55.767 * The server is now ready to accept connections on port 6379
app_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
app_1 | * Restarting with stat
app_1 | * Debugger is active!
app_1 | * Debugger pin code: 299-635-701
Данный пример увеличит счетчик просмотров в Redis. Откройте localhost в браузере и проверьте.
Теперь вы можете поиграться с различными образами из Docker Hub или, если хотите, создать свои собственные образы, соблюдая лучшие практики, описанные ниже. Единственное, что можно добавить насчет использования docker-compose: всегда давайте точные имена вашим томам в docker-compose.yml (если в образе есть тома). Это простое правило спасет вас от проблем при проверке ваших томов.
version: '2'
services:
...
redis:
image: redis:3.2-alpine
volumes:
- redis_data:/data
volumes:
redis_data:version: '2'
services:
...
redis:
image: redis:3.2-alpine
volumes:
- redis_data:/data
volumes:
redis_data:
В этому случае redis_data будет именем внутри docker-compose.yml, для настоящего имени тома будет добавлен префикс с именем проекта.
Чтобы просмотреть список томов:
docker volume ls
Вывод консоли:
DRIVER VOLUME NAME
local apptest_redis_data
Без точного имени тома там будет находиться UUID. Вот пример с локального компьютера:
DRIVER VOLUME NAME
local ec1a5ac0a2106963c2129151b27cb032ea5bb7c4bd6fe94d9dd22d3e72b2a41b
local f3a664ce353ba24dd43d8f104871594de6024ed847054422bbdd362c5033fc4c
local f81a397776458e62022610f38a1bfe50dd388628e2badc3d3a2553bb08a5467f
local f84228acbf9c5c06da7be2197db37f2e3da34b7e8277942b10900f77f78c9e64
local f9958475a011982b4dc8d8d8209899474ea4ec2c27f68d1a430c94bcc1eb0227
local ff14e0e20d70aa57e62db0b813db08577703ff1405b2a90ec88f48eb4cdc7c19
local polls_pg_data
local polls_public_files
local polls_redis_data
local projectdev_pg_data
local projectdev_redis_data
Стайлгайды Docker
У Docker есть некоторые ограничения и требования, которые зависят от архитектуры системы (приложений, которые вы упаковываете в контейнеры). Можно игнорировать эти требования или найти какие-нибудь пути обхода, но в этом случае вы не получите все преимущества использования Docker. Настоятельно рекомендуется следовать следующим советам:
- 1 приложение = 1 контейнер.
- Запускайте процесс на переднем плане (не используйте systemd, upstart или другие похожие инструменты).
- Для хранения данных вне контейнера используйте тома.
- Не иcпользуйте SSH (если вам надо залезть внутрь контейнера, используйте docker exec).
- Избегайте ручных настроек или действий внутри контейнера.
- Включайте только необходимый контекст — используйте .dockerignore файл (как .gitignore в git).
- Избегайте установки ненужных пакетов — это займет лишнее дисковое пространство.
- Используйте кэш. Добавьте контекст, который часто меняется, например, исходный код вашего проекта, в конец Dockerfile — кэш Docker будет использоваться более эффективно.
- Будьте осторожны с томами. Вы должны помнить, какие данные находятся в томах. Поскольку тома постоянны и не исчезают вместе с контейнерами, следующий контейнер будет использовать данные, которые были созданы предыдущим контейнером.
- Используйте переменные окружения: RUN, EXPOSE, VOLUME. Это сделает ваш Dockerfile более гибким.
Заключение
В заключение стоит отметить, что Docker стал одним из необходимых инструментов разработчика, наравне с различными IDE и Git.
Источник - https://tproger.ru/translations/how-to-start-using-docker
Дайджест новых статей по интернет-маркетингу на ваш email
Новые статьи и публикации
- 2024-11-26 » Капитан грузового судна, или Как начать использовать Docker в своих проектах
- 2024-11-26 » Обеспечение безопасности ваших веб-приложений с помощью PHP OOP и PDO
- 2024-11-22 » Ошибки в Яндекс Вебмастере: как найти и исправить
- 2024-11-22 » Ошибки в Яндекс Вебмастере: как найти и исправить
- 2024-11-15 » Перенос сайта на WordPress с одного домена на другой
- 2024-11-08 » OSPanel 6: быстрый старт
- 2024-11-08 » Как установить PhpMyAdmin в Open Server Panel
- 2024-09-30 » Как быстро запустить Laravel на Windows
- 2024-09-25 » Next.js
- 2024-09-05 » OpenAI рассказал, как запретить ChatGPT использовать содержимое сайта для обучения
- 2024-08-28 » Чек-лист: как увеличить конверсию интернет-магазина на примере спортпита
- 2024-08-01 » WebSocket
- 2024-07-26 » Интеграция с Яндекс Еда
- 2024-07-26 » Интеграция с Эквайринг
- 2024-07-26 » Интеграция с СДЕК
- 2024-07-26 » Интеграция с Битрикс-24
- 2024-07-26 » Интеграция с Travelline
- 2024-07-26 » Интеграция с Iiko
- 2024-07-26 » Интеграция с Delivery Club
- 2024-07-26 » Интеграция с CRM
- 2024-07-26 » Интеграция с 1C-Бухгалтерия
- 2024-07-24 » Что такое сторителлинг: техники и примеры
- 2024-07-17 » Ошибка 404: что это такое и как ее использовать для бизнеса
- 2024-07-03 » Размещайте прайс-листы на FarPost.ru и продавайте товары быстро и выгодно
- 2024-07-01 » Профилирование кода в PHP
- 2024-06-28 » Изучаем ABC/XYZ-анализ: что это такое и какие решения с помощью него принимают
- 2024-06-17 » Зачем вам знать потребности клиента
- 2024-06-11 » Что нового в работе Яндекс Метрики: полный обзор обновления
- 2024-06-11 » Поведенческие факторы ранжирования в Яндексе
- 2024-06-11 » Скорость загрузки сайта: почему это важно и как влияет на ранжирование
Лично я люблю землянику со сливками, но рыба почему-то предпочитает червяков. Вот почему, когда я иду на рыбалку, я думаю не о том, что люблю я, а о том, что любит рыба. (Дейл Карнеги / БИЗНЕС) |
Мы создаем сайты, которые работают! Профессионально обслуживаем и продвигаем их , а также по всей России и ближнему зарубежью с 2006 года!
Как мы работаем
Заявка
Позвоните или оставьте заявку на сайте.
Консультация
Обсуждаем что именно Вам нужно и помогаем определить как это лучше сделать!
Договор
Заключаем договор на оказание услуг, в котором прописаны условия и обязанности обеих сторон.
Выполнение работ
Непосредственно оказание требующихся услуг и работ по вашему заданию.
Поддержка
Сдача выполненых работ, последующие корректировки и поддержка при необходимости.