Выход Докера в настоящий бой (3)

Самодельный образ Docker

Вообще говоря, когда наша разработка программы будет завершена, будет создан новый образ вместе с программными файлами и операционной средой. Чтобы сделать образ, вам нужно написать Dockerfile. DockeFile состоит из нескольких команд, часто используемые команды:

  • ОТ: создать новый образ на основе изображения. Формат: FROM имя образа: версия образа.
  • КОПИРОВАТЬ: Копировать файлы с хоста, поддерживая подстановочные знаки, такие как ?, * и т. д. Формат следующий: COPY путь к исходному файлу путь к целевому файлу.
  • ДОБАВИТЬ: добавить файлы с хост-компьютера, формат такой же, как и у COPY, разница в том, что, когда файл является сжатым файлом, он будет распакован по целевому пути.
  • RUN: команда оболочки, выполняемая в процессе создания нового образа. Формат: RUN командная строка оболочки. Обратите внимание, что эта команда оболочки будет выполняться внутри контейнера.
  • CMD: команда для запуска в экземпляре контейнера, формат такой же, как RUN. Обратите внимание, что если команда указана во время запуска докера, содержимое CMD не будет выполнено.
  • ENTRYPOINT: команда для запуска в экземпляре контейнера, формат такой же, как у CMD. Обратите внимание, что если во время запуска докера указана команда, она будет передана в ENTRYPOINT в качестве параметра командной строки.
  • ENV: создайте переменную среды в контейнере в следующем формате: значение имени переменной ENV.

Обратите внимание, что в образе Docker существует концепция слоев. Каждый раз, когда выполняется команда RUN, будет создаваться слой. Слишком много слоев увеличит размер файла образа. Попробуйте использовать && в команде RUN, чтобы соединить несколько команд оболочки, чтобы уменьшить количество команд RUN, что может эффективно уменьшить размер файла образа.

5.1 Самодельное изображение отображения содержимого текстового файла

Напишите cat.py, который получает имя файла, читает файл с помощью python и отображает содержимое файла:

import os
import sys

input = sys.argv[1]

with open(input, "r") as fp:
    print(fp.read())

Этот пример относительно прост, сокращенно Dockerfile выглядит следующим образом:

FROM python:3.8
WORKDIR /files
COPY cat.py /cat.py
ENTRYPOINT ["python", "/cat.py"]

Значение этого Dockerfile:

  • Зеркало на основе python:3.8
  • Рабочий каталог команды запуска контейнера — /files, при запуске образа нам нужно смонтировать определенный каталог хоста в каталог /files контейнера
  • Скопируйте cat.py в корневой каталог контейнера.
  • Запустите команду python /cat.py при запуске.

Следует отметить, что существует два способа записи ENTRYPOINT:

ENTRYPOINT python /cat.py
ENTRYPOINT ["python", "/cat.py"]

Здесь используется второй способ записи, потому что нам нужно передать параметры контейнеру извне. Выполните команду для компиляции образа Docker:

docker build -t cat:1.0 .

В этой команде значение -t - цель, то есть сгенерированный - это cat, номер версии 1.0, не забудьте последнюю, это называется контекстным путем, что означает, что докер строит image, и иногда вы хотите использовать один локальный файл (например, для копирования), после того как команда сборки docker узнает этот путь, она упакует все содержимое по этому пути.

Таким образом создается наш первый образ, для его запуска используйте следующую команду:

docker run -it -v ~/docker_test/cat/files:/files cat:1.0 test.txt

Вы можете увидеть содержимое ~/docker_test/cat/files/test.txt.

5.2 Самодельный образ веб-сервера

Мы используем tornado для разработки сайта, а в официальном образе python нет библиотеки tornado, которую нужно установить при создании образа. Протестированный ws.py выглядит следующим образом:

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello world")

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(handlers=[(r"/", IndexHandler)])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

Напишите Dockerfile следующим образом:

FROM python:3.8
WORKDIR /ws
COPY ws.py /ws/ws.py
RUN pip install tornado
CMD python hello.py

Здесь мы проверяем разницу между CMD и ENTRYPOINT. Выполните следующую команду в каталоге, где находится Dockerfile:

docker build -t ws:1.0 .

После завершения выполнения используйте образы докеров, чтобы увидеть сгенерированный образ, а затем используйте следующую команду для запуска:

docker run -it -p 8000:8000 ws:1.0

Введите ip хоста и порт 8000 в браузере, и вы сможете увидеть страницу. В этом примере я использую команду запуска CMD.Если в docker run указаны другие команды, эта команда не будет выполняться, например:

$ docker run -it -p 8000:8000 ws:1.0 python
Python 3.8.7 (default, Dec 22 2020, 18:46:25) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 

На данный момент команда python выполняется в контейнере, а не в нашем сервисе. В большинстве случаев мы хотим передать параметры нашему сервису в команде запуска docker вместо переопределения команды выполнения, тогда мы должны использовать ENTRYPOINT вместо CMD:

FROM python:3.8
WORKDIR /ws
COPY ws.py /ws/ws.py
RUN pip install tornado
ENTRYPOINT python ws.py

Приведенный выше метод записи не поддерживает передачу параметров, ENTRYPOINT и CMD также поддерживают другой метод записи:

FROM python:3.8
WORKDIR /ws
COPY ws.py /ws/ws.py
RUN pip install tornado
ENTRYPOINT ["python", "ws.py"]

Используя этот способ записи, параметры команды запуска docker можно передать в hello.py:

docker run -it -p 8000:9000 ws:1.0 --port=9000

В этой команде --port=9000 передается в качестве параметра hello.py, поэтому порт внутри контейнера становится 9000. При работе в производственной среде параметр -it не используется, но используется параметр -d, чтобы позволить контейнеру работать в фоновом режиме:

$ docker run -d -p 8000:9000 ws:1.0 --port=9000
4a2df9b252e2aff6a8853b3a8bf46c0577545764831bb7557b836ddcd85cba70
$ docker ps                                       
CONTAINER ID   IMAGE        COMMAND                  CREATED           STATUS            PORTS                    NAMES
4a2df9b252e2   hello:1.0    "python ws.py --p…"   9 seconds ago     Up 8 seconds      0.0.0.0:8000->9000/tcp   elegant_sammet

Таким образом, даже если текущая консоль будет закрыта, контейнер не остановится.

5.3 Самодельный образ службы аппланера

Далее делаем образ сервиса, написанный с помощью apscheduler, код такой:

import sys
import shutil
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger

def scan_files():
    shutil.copytree(sys[1], sys[2])

scheduler = BlockingScheduler()
scheduler.add_job(
    scan_files,
    trigger=CronTrigger(minute="*"),
    misfire_grace_time=30
)

Dockerfile также удобен:

FROM python:3.8
WORKDIR /
COPY sch.py /sch.py
RUN pip install apscheduler
ENTRYPOINT ["python", "sch.py"]

Создайте зеркальное изображение:

docker build -t sch:1.0 .

Это должно работать. Для копирования файлов требуются два каталога. Во время выполнения вы можете использовать -v дважды для монтирования разных каталогов:

docker run -d -v ~/docker_test/sch/src:/src -v ~/docker_test/sch/dest:/dest sch:1.0 /src /dest

Supongo que te gusta

Origin blog.csdn.net/qq_28165595/article/details/131878132
Recomendado
Clasificación