danoque microservices repository
danoque@danoque:~/Devops/Docker/danoque_microservices/dockermonolith$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
d1165f221234: Pull complete
Digest: sha256:776b0895d5e2fcd5e80bcdd607adc45461ba11143ef3df531174bf00679f43fe
Status: Downloaded newer image for hello-world:latest
### Рассмотрим основные команды для взаимодействия
Список запущенных контейнеров:
```bash
docker ps
Список всех контейнеров:
docker ps -a
Список сохраненных образов:
docker images
Команда run создает и запускает контейнер из image:
docker run -it ubuntu:18.04 /bin/bash
Сортировка контейнеров по дате создания:
docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.CreatedAt}}\t{{.Names}}"
Запуск остановленного контейнера:
docker start <u_container_id>
attach подсоединяет терминал к созданному контейнеру:
docker attach <u_container_id>
Запуск процесса внутри контейнера:
docker exec -it <u_container_id> bash
Создание image из контейнера:
docker commit <u_container_id> yourname/ubuntu-tmp-file
Создание image:
danoque@danoque:~/Devops/Docker/danoque_microservices/dockermonolith$ docker commit 4babfbfd5179 danoque/ubuntu-tmp-file
sha256:fjd63f8a8d593c3c1a3f6fjg743e6a3f119e17165f6g02ebc61a57fhd63hdjcx
выведем список образов:
danoque@danoque:~/Devops/Docker/danoque_microservices/dockermonolith$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
danoque/otus-reddit 1.0 abdcfa63347c 7 weeks ago 646MB
reddit latest e151e7920ff5 7 weeks ago 646MB
danoque/ubuntu-tmp-file latest cd0bf7e6b940 7 weeks ago 63.1MB
ubuntu 18.04 39a8cfeef173 2 months ago 63.1MB
hello-world latest d1165f221234 2 months ago 13.3kB
Выполним сравнение вывода двух команд и исследуем контейнер:
danoque@danoque:~/Devops/Docker/danoque_microservices/dockermonolith$ docker inspect 4babfbfd5179
[
{
"Id": "4hfjduf75g791d8b8506a03bc386f7dhd54haa0488ba203ff94a57d8jhf51fxb",
"Created": "2021-07-29T18:18:54.9688137Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 3861,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-07-29T19:44:35.3451252Z",
"FinishedAt": "2021-07-29T19:45:28.7651247+03:00"
},
"Image": "sha256:4hf6dfeef1730fhdnc62kzafe12368560fe62ef9d517808855f7bda798jf6dfga",
"ResolvConfPath": "/var/snap/docker/common/var-lib-docker/containers/4babfbfd51791d8b8506a03bc386c128a208a90488ba203ff94a57d8dfa1afe4/resolv.conf",
"HostnamePath": "/var/snap/docker/common/var-lib-docker/containers/4babfbfd51791d8b8506a03bc386c128a208a90488ba203ff94a57d8dfa1afe4/hostname",
"HostsPath": "/var/snap/docker/common/var-lib-docker/containers/4babfbfd51791d8b8506a03bc386c128a208a90488ba203ff94a57d8dfa1afe4/hosts",
"LogPath": "/var/snap/docker/common/var-lib-docker/containers/3jfbvnc6730791d8b8506a03bc386c128a208a90488ba203ff94a57d8dfa1afe4/4babfbfd51791d8b8506a03bc386c128a208a90488ba203ff94a57d8dfa1afe4-json.log",
"Name": "/cool_elgamal",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "docker-default",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Capabilities": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/snap/docker/common/var-lib-docker/overlay2/bf80d30195dc261d894a371e9672949e4044294af1bd99c99549db9a711ca045-init/diff:/var/snap/docker/common/var-lib-docker/overlay2/51024c3a7ac7b0bfc29ac22720cf818e97dc872ac7f926249c3878dc35cabcd1/diff",
"MergedDir": "/var/snap/docker/common/var-lib-docker/overlay2/bf80d30195dc261d894a371e9672949e4044294af1bd99c99549db9a711ca045/merged",
"UpperDir": "/var/snap/docker/common/var-lib-docker/overlay2/bf80d30195dc261d894a371e9672949e4044294af1bd99c99549db9a711ca045/diff",
"WorkDir": "/var/snap/docker/common/var-lib-docker/overlay2/bf80d30195dc261d894a371e9672949e4044294af1bd99c99549db9a711ca045/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "4babfbfd5179",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash"
],
"Image": "ubuntu:18.04",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "14dc3635995c0076526dc79978f04c267aa41764b54c2bad78d9104f55667464",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/run/snap.docker/netns/14dc3635995c",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "09a01a02e46cb3ef4be9890b9db8f86c4e6456a92d5f7787bb37871995956f3f",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "f8478e15573c5cb64f4c26283c55dce7595ff896ccc7c948d5819e79a840d0bb",
"EndpointID": "09a01a02e46cb3ef4be9890b9db8f86c4e6456a92d5f7787bb37871995956f3f",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
Исследование образа:
danoque@danoque:~/Devops/Docker/danoque_microservices/dockermonolith$ docker inspect d1165f221234
[
{
"Id": "sha256:4kg8gi5489fgj3493c3c1a3f6d94a93e6a3f119e17965f6f02eb89ui9fghir58954g",
"RepoTags": [
"denis_petrov/ubuntu-tmp-file:latest"
],
"RepoDigests": [],
"Parent": "sha256:74hfyd63hf894ce93cefe12368560fe62ef9d517808855f7bda79a1eb697",
"Comment": "",
"Created": "2021-08-11T15:31:45.5264088Z",
"Container": "a3578c0271dcb8506a03bc386c128a208a90488ba203ff94a57d8dfa1h8fhf6",
"ContainerConfig": {
"Hostname": "4babfbfd5179",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash"
],
"Image": "ubuntu:18.04",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"DockerVersion": "19.03.13",
"Author": "",
"Config": {
"Hostname": "a3578c0271dc",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash"
],
"Image": "ubuntu:18.04",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"Architecture": "amd64",
"Os": "linux",
"Size": 63137505,
"VirtualSize": 63137505,
"GraphDriver": {
"Data": {
"LowerDir": "/var/snap/docker/common/var-lib-docker/overlay2/51024c3a7ac7b0bfc29ac22720cf818e97dc872ac7f926249c3878dc35cabcd1/diff",
"MergedDir": "/var/snap/docker/common/var-lib-docker/overlay2/955a9dbbf53a4c00a53e48ab5571e57e26ebfaaceebd8c435b4f5f726eaa6214/merged",
"UpperDir": "/var/snap/docker/common/var-lib-docker/overlay2/955a9dbbf53a4c00a53e48ab5571e57e26ebfaaceebd8c435b4f5f726eaa6214/diff",
"WorkDir": "/var/snap/docker/common/var-lib-docker/overlay2/955a9dbbf53a4c00a53e48ab5571e57e26ebfaaceebd8c435b4f5f726eaa6214/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:54yrththw6ryh4h5454fe31c79cdf54470afe4dg54uh4f4y89g4r89rg89q423i",
"sha256:w54hq34q344h6rj67w46db4b7fc8f9eb7eea34dffdcbc1506f3b3489rguh9g48"
]
},
"Metadata": {
"LastTagTime": "2021-07-29T18:55:45.5627452+03:00"
}
}
]
Контейнер и образ различаются следующим образом, что контейнер является экземпляром образа. Именно контейнер содержит верхний слой доступный для записи, а непосредственно в образе содержатся слои только для чтения. Можно создать еще один неизменный слой контейнера поверх исходного образа, т.е. на основе контейнера создаётся образ, в который сохранится текущее состояние контейнера.
docker rm $(docker ps -a -q)
docker rmi $(docker images -q)
Создание машины:
docker-machine create <имя>
После создания хоста и установки на нем Docker engine, работать с удаленным Docker'ом можно с помощью команды:
eval $(docker-machine env <имя>)
Эта же команда переключается между разными машинами.
Переключение на локальный докер:
eval $(docker-machine env --unset)
Удаление:
docker-machine rm <имя>
docker build -t reddit:latest .
Sending build context to Docker daemon 7.168kB
Step 1/11 : FROM ubuntu:18.04
18.04: Pulling from library/ubuntu
...
Successfully built 0192d5086c2e
Successfully tagged reddit:latest
Запустим контейнер:
docker run --name reddit -d --network=host reddit:latest
Загрузка образа в Docker HUB
$ docker push danoque/otus-reddit:1.0
Локально запусти Docker образа из репозитория Docker HUB:
docker run --name reddit -d -p 9292:9292 danoque/otus-reddit:1.0
Unable to find image 'danoque/otus-reddit:1.0' locally
1.0: Pulling from danoque/otus-reddit
danoque@danoque:~/Devops/Docker/danoque_microservices/dockermonolith$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
520a9e38971d danoque/otus-reddit:1.0 "/start.sh" 7 weeks ago Exited (1) 7 weeks ago reddit2
Подключимся к ранее созданному Docker host’у:
$ docker-machine ls
$ eval $(docker-machine env docker-host)
Локально сохраним файлы в каталог src, он станет главным рабочим каталогом, в котором расположатся: post-py - сервис отвечающий за написание постов comment - сервис отвечающий за написание комментариев ui - веб-интерфейс, работающий с другими сервисами
Применим линтер для оптимизации Dockerfile на примере comment:
danoque@danoque:~/Devops/docker-3/src/comment$ hadolint Dockerfile
Dockerfile:2 DL3008 warning: Pin versions in apt get install. Instead of `apt-get install <package>` use `apt-get install <package>=<version>`
Dockerfile:2 DL3009 info: Delete the apt-get lists after installing something
Dockerfile:2 DL3015 info: Avoid additional packages by specifying `--no-install-recommends`
Dockerfile:6 DL3020 error: Use COPY instead of ADD for files and folders
Постараемся исправить все недочёты + перепишем команды для RUN под более легкий alpine:
FROM ruby:2.3-alpine
ENV APP_HOME /app RUN mkdir $APP_HOME WORKDIR $APP_HOME
COPY Gemfile* $APP_HOME/
RUN apt-get update -qq --no-install-recommends
&& apt-get install -y --no-install-recommends
&& build-essential --no-install-recommends
&& bundle install --no-install-recommends
&& apt-get clean && rm -rf /var/lib/apt/lists/*
COPY . $APP_HOME
ENV COMMENT_DATABASE_HOST comment_db ENV COMMENT_DATABASE comment
CMD ["puma"]
Выполним анологичные манипуляции с Dockerfile для "post" и "ui". Выполним сборку приложения: Скачаем последний образ MongoDB:
docker pull mongo:latest
Соберем образы с нашими сервисами:
docker build -t danoque/post:1.0 ./post-py
docker build -t danoque/comment:1.0 ./comment
docker build -t danoque/ui:1.0 ./ui
Создадим специальную сеть для приложения:
docker network create reddit
И запустим наши контейнеры:
docker run -d --network=reddit --network-alias=post_db --network-alias=comment_db -v reddit_db:/data/db mongo:latest
docker run -d --network=reddit --network-alias=post danoque/post:1.0
docker run -d --network=reddit --network-alias=comment danoque/comment:1.0
docker run -d --network=reddit -p 9292:9292 danoque/ui:2.0
Проекты успешно собираются и сервис доступен.Теперь, чтобы добавить возможность сохранения постов после остановки и запуска контейнеров выполним следующие инструкции:
Выключим старые копии контейнеров:
docker kill $(docker ps -q)
Запустим новые копии контейнеров:
docker run -d --network=reddit --network-alias=post_db --network-alias=comment_db -v reddit_db:/data/db mongo:latest
docker run -d --network=reddit --network-alias=post danoque/post:1.0
docker run -d --network=reddit --network-alias=comment danoque/comment:1.0
docker run -d --network=reddit -p 9292:9292 danoque/ui:2.0