Начало работы, часть 2: Контейнеры
Введение
Пришло время начать создание приложения Docker. Мы начинаем в нижней части иерархии такого приложения, которое является контейнером, который мы рассмотрим на этой странице. Выше этого уровня - это сервис, который определяет, как контейнеры ведут себя в процессе производства, описанные в части 3. Наконец, на верхнем уровне находится стек, определяющий взаимодействие всех сервисов, описанных в части 5.
- Stack
- Services
- Container(Вы изучите на этой странице)
Ваша новая среда разработки
Раньше, если бы вы начали писать приложение Python, ваш первый заказ заключался в том, чтобы установить время выполнения Python на ваш компьютер. Но это создает ситуацию, когда среда на вашем компьютере должна быть идеальной для вашего приложения, чтобы он работал как ожидалось, а также должен соответствовать вашей производственной среде.
С Docker вы можете просто захватить портативную среду исполнения Python как изображение, при этом не требуется установка. Затем ваша сборка может включать в себя базовое изображение Python прямо рядом с вашим кодом приложения, гарантируя, что ваше приложение, его зависимости и время выполнения все перемещаются вместе.
Эти портативные изображения определяются тем, что называется Dockerfile.
Определить контейнер с Dockerfile
Dockerfile определяет, что происходит в среде внутри вашего контейнера. Доступ к таким ресурсам, как сетевые интерфейсы и дисководы, виртуализирован внутри этой среды, которая изолирована от остальной части вашей системы, поэтому вам нужно отображать порты во внешний мир и быть конкретными о том, какие файлы вы хотите «скопировать» это окружающая среда. Однако, после этого, вы можете ожидать, что сборка вашего приложения, определенного в этом файле Docker, будет вести себя точно так же, где бы он ни работал.
Dockerfile
Создайте пустой каталог. Измените директории (cd) в новый каталог, создайте файл Dockerfile, скопируйте и вставьте следующий контент в этот файл и сохраните его. Обратите внимание на комментарии, которые объясняют каждое утверждение в вашем новом файле Docker.
# Использовать официальную среду исполнения Python как родительское изображение
FROM python:2.7-slim
# Установите рабочий каталог в /app
WORKDIR /app
# Скопируйте содержимое текущего каталога в контейнер /app
ADD . /app
# Установите все необходимые пакеты, указанные в requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt
# Сделать порт 80 доступным для мира за пределами этого контейнера
EXPOSE 80
# Определить переменную среды
ENV NAME World
# Запустите app.py при запуске контейнера
CMD ["python", "app.py"]
Вы за прокси-сервером?
Прокси-серверы могут блокировать подключения к вашему веб-приложению после его запуска и запуска. Если вы находитесь за прокси-сервером, добавьте следующие строки в свой файл Docker, используя команду ENV, чтобы указать хост и порт для ваших прокси-серверов:
# Установите прокси-сервер, замените host: port со значениями для ваших серверов
ENV http_proxy host:port
ENV https_proxy host:port
Добавьте эти строки перед вызовом в pip, чтобы установка прошла успешно.
Этот файл Dockerfile относится к паре файлов, которые мы еще не создали, а именно app.py и requirements.txt. Давайте создадим следующий.
Само приложение
Создайте еще два файла, requirements.txt и app.py и поместите их в ту же папку с файлом Docker. Это завершает наше приложение, которое, как вы видите, довольно простое. Когда вышеуказанный файл Dockerfile встроен в изображение, app.py и requirements.txt присутствует из-за этой команды ADD Dockerfile, а выход из app.py доступен через HTTP благодаря команде EXPOSE.
requirements.txt
Flask
Redis
app.py
from flask import Flask
from redis import Redis, RedisError
import os
import socket
# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
app = Flask(__name__)
@app.route("/")
def hello():
try:
visits = redis.incr("counter")
except RedisError:
visits = "<i>cannot connect to Redis, counter disabled</i>"
html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>" \
"<b>Visits:</b> {visits}"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
Теперь мы видим, что pip install -r requirements.txt
устанавливает библиотеки Flask и Redis для Python, и приложение печатает переменную среды NAME, а также вывод вызова socket.gethostname (). Наконец, поскольку Redis не работает (поскольку мы только установили библиотеку Python, а не сами Redis), мы должны ожидать, что попытка его использования здесь не удалась и выдает сообщение об ошибке.
Примечание.
Доступ к имени хоста, когда внутри контейнера извлекается идентификатор контейнера, который похож на идентификатор процесса для исполняемого исполняемого файла.
Это оно! Вам не нужен Python или что-либо в файле requirements.txt вашей системы, а также не создает и не запускает этот образ в вашей системе. Не похоже, что вы действительно создали среду с Python и Flask, но у вас есть.
Создайте приложение
Мы готовы создать приложение. Убедитесь, что вы все еще находитесь на верхнем уровне своего нового каталога. Вот что должно показать:
$ ls
Dockerfile app.py requirements.txt
Теперь запустите команду сборки. Это создает изображение Docker, которое мы собираемся пометить с помощью -t, чтобы оно имело дружественное имя.
docker build -t friendlyhello .
Где ваше построенное изображение(образ)? Он находится в локальном реестре изображений Docker вашего компьютера:
$ docker image ls
REPOSITORY TAG IMAGE ID
friendlyhello latest 326387cea398
Запустить приложение
Запустите приложение, сопоставляя порт 4000 вашего компьютера с опубликованным портом 80 контейнера, используя -p:
docker run -p 4000:80 friendlyhello
Вы должны увидеть сообщение о том, что Python обслуживает ваше приложение по адресу http://0.0.0.0:80. Но это сообщение поступает изнутри контейнера, который не знает, что вы сопоставили порт 80 этого контейнера с 4000, создавая правильный URL http: // localhost:4000.
Перейдите к этому URL-адресу в веб-браузере, чтобы просмотреть отображаемый контент, который был загружен на веб-странице.
Примечание.
Если вы используете Docker Toolbox в Windows 7, используйте IP-адрес Docker Machine вместо localhost. Например, http://192.168.99.100:4000/. Чтобы найти IP-адрес, используйте команду docker-machine ip.
Вы также можете использовать команду curl в оболочке для просмотра одного и того же содержимого.
$ curl http://localhost:4000
<h3>Hello World!</h3><b>Hostname:</b> 8fc990912a14<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
Это переназначение портов 4000: 80 заключается в том, чтобы продемонстрировать разницу между тем, что вы ЭКСПОЗИЦИЯ в файле Docker, и тем, что вы публикуете с помощью docker run -p
. На последующих шагах мы просто сопоставляем порт 80 на хосте с портом 80 в контейнере и используем http: // localhost.
Нажмите CTRL + C в своем терминале, чтобы выйти.
В Windows явно остановите контейнер
В системах Windows CTRL + C не останавливает контейнер. Итак, сначала введите CTRL + C, чтобы получить подсказку назад (или откройте другую оболочку), затем введите docker container ls, чтобы отобразить запущенные контейнеры, а затем контейнерный контейнер stop <Container NAME или ID>, чтобы остановить контейнер. В противном случае вы получите ответ об ошибке от демона, когда вы попытаетесь повторно запустить контейнер на следующем шаге.
Теперь давайте запустим приложение в фоновом режиме в отдельном режиме:
docker run -d -p 4000:80 friendlyhello
Вы получаете длинный идентификатор контейнера для своего приложения, а затем отбрасываете его обратно на терминал. Ваш контейнер работает в фоновом режиме. Вы также можете увидеть сокращенный идентификатор контейнера с контейнером docker ls
(и обе работают взаимозаменяемо при запуске команд):
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED
1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago
Обратите внимание, что CONTAINER ID
соответствует тому, что находится наhttp://localhost:4000
.
Теперь используйте докер-контейнер, чтобы завершить процесс, используя идентификатор контейнера:
docker container stop 1fa4ab2cf395
Поделитесь своим изображением(образом)
Чтобы продемонстрировать мобильность того, что мы только что создали, давайте загрузим наше построенное изображение и запустим его где-то еще. В конце концов, вам нужно знать, как нажать на реестры, когда вы хотите развернуть контейнеры для производства.
Реестр представляет собой набор репозиториев, а репозиторий - это коллекция изображений, вроде хранилища GitHub, за исключением того, что код уже создан. Учетная запись в реестре может создавать множество репозиториев. Доклер CLI использует общедоступный реестр Docker по умолчанию.
Примечание.
Мы используем публичный реестр Docker здесь только потому, что он бесплатный и предварительно настроенный, но есть много публичных на выбор, и вы даже можете настроить свой собственный реестр с помощью Docker Trusted Registry.
Войдите в систему с помощью своего Docker ID
Если у вас нет учетной записи Docker, зарегистрируйтесь на сайте cloud.docker.com. Обратите внимание на свое имя пользователя.
Войдите в публичный реестр Docker на вашем локальном компьютере.
$ docker login
Tag the image
Нотация для связывания локального образа с репозиторием в реестре - это username/repository:tag. Тег является необязательным, но рекомендуется, так как это механизм, который реестры используют, чтобы дать Docker изображения версии. Дайте репозиторий и пометьте значимые имена для контекста, например get-started: part2. Это помещает изображение в репозиторий с запуском и помещает его как part2.
Теперь поместите все это вместе, чтобы пометить изображение. Запустите изображение тега docker с именами пользователей, репозиториев и тегов, чтобы изображение загрузилось в нужное место. Синтаксис команды:
docker tag image username/repository:tag
Например:
docker tag friendlyhello john/get-started:part2
Запуститеdocker image ls
, чтобы увидеть ваше недавно помеченное изображение.
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
friendlyhello latest d9e555c53008 3 minutes ago 195MB
john/get-started part2 d9e555c53008 3 minutes ago 195MB
python 2.7-slim 1c7128a655f6 5 days ago 183MB
...
Опубликовать изображение(образ)
Загрузите помеченное изображение в репозиторий:
docker push username/repository:tag
После завершения результаты этой загрузки общедоступны. Если вы входите в Docker Hub, вы увидите новое изображение с его командой pull.
Вытяните и запустите изображение из удаленного репозитория
С этого момента вы можете использовать запуск докеров и запускать приложение на любом компьютере с помощью этой команды:
docker run -p 4000:80 username/repository:tag
Если изображение не доступно локально на машине, Docker вытаскивает его из репозитория.
$ docker run -p 4000:80 john/get-started:part2
Unable to find image 'john/get-started:part2' locally
part2: Pulling from john/get-started
10a267c67f42: Already exists
f68a39a6a5e4: Already exists
9beaffc0cf19: Already exists
3c1fe835fb6b: Already exists
4c9f1fa8fcb8: Already exists
ee7d8f576a14: Already exists
fbccdcced46e: Already exists
Digest: sha256:0601c866aab2adcc6498200efd0f754037e909e5fd42069adeff72d1e2439068
Status: Downloaded newer image for john/get-started:part2
* Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
Независимо от того, где выполняется запуск docker, он тянет ваше изображение вместе с Python и всеми зависимостями от requirements.txt и запускает ваш код. Все это перемещается вместе в аккуратном маленьком пакете, и вам не нужно устанавливать что-либо на главной машине для Docker для ее запуска.
Заключение второй части
Это все для этой страницы. В следующем разделе мы узнаем, как масштабировать наше приложение, запустив этот контейнер в службе.
Вот список основных команд Docker с этой страницы и некоторые связанные с ними, если вы хотите немного изучить, прежде чем двигаться дальше.
docker build -t friendlyhello . # Создайте изображение, используя этот каталог Dockerfile
docker run -p 4000:80 friendlyhello # Run "friendlyname" сопоставив порты 4000 to 80
docker run -d -p 4000:80 friendlyhello # То же самое, но в отдельном режиме
docker container ls # Список всех запущенных контейнеров
docker container ls -a # Перечислите все контейнеры, даже те, которые не работают
docker container stop <hash> # Изящно остановите указанный контейнер
docker container kill <hash> # Выключение принудительной остановки указанного контейнера
docker container rm <hash> # Удалить указанный контейнер с этой машины
docker container rm $(docker container ls -a -q) # Удалить все контейнеры
docker image ls -a # Список всех изображений на этой машине
docker image rm <image id> # Удалить указанное изображение с этой машины
docker image rm $(docker image ls -a -q) # Удалить все изображения с этой машины
docker login # Войдите в этот сеанс CLI, используя учетные данные Docker
docker tag <image> username/repository:tag # Тег <image> для загрузки в реестр
docker push username/repository:tag # Загрузка отмеченного изображения в реестр
docker run username/repository:tag # Запустить образ из реестра