Навроцкий Артем
/proc/sys/kernel/core_pattern
)Docker использует встроенную поддержку контейнеров.
Docker Server запускается под Linux внутри виртуальной машины.
Виртуальная машина с Docker Server:
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 46 3 18.59GB 17.33GB (93%)
Containers 3 2 1.169GB 2.198kB (0%)
Local Volumes 1 1 1.049GB 0B (0%)
Build Cache 6 0 0B 0B
$ docker system prune
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all dangling images
- all dangling build cache
Are you sure you want to continue? [y/N]
$ docker container ls -a
$ docker container ps -a
$ docker container prune
$ docker image ls
$ docker images
$ docker image prune
$ docker run --rm -it alpine:latest sh
# ls
bin home mnt root srv usr
dev lib opt run sys var
etc media proc sbin tmp
# exit
$ docker run --rm \
--hostname=foobar \
--env FOO=bar \
--env BAR=baz \
alpine:latest \
env
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin
HOSTNAME=foobar
FOO=bar
BAR=baz
HOME=/root
$ docker run --rm -it --net host nginx
$ docker run --rm -it --net host ubuntu hostname -I
172.16.1.150 172.17.0.1
$ docker run --rm -it \
--publish 8080:80 \
--publish :8081:80/tcp \
--publish 127.0.0.1:8082:80/tcp \
nginx
$ docker run --rm -it ubuntu hostname -I
172.17.0.3
Если порт занят, то под MacOS контейнер запустится, но трафик пойдет в локальный сервис, а не в контейнер.
$ docker run --rm --volume $(pwd):/workspace:ro \
alpine \
ls /workspace
Jenkinsfile
config.yaml
content
hugo.sh
public
resources
start.sh
static
themes
$ docker run --rm ubuntu:latest id
uid=0(root) gid=0(root) groups=0(root)
$ docker run --rm --user 1000:100 ubuntu:latest id
uid=1000 gid=100(users) groups=100(users)
$ docker run --rm bitnami/elasticsearch:latest id
uid=1001 gid=0(root) groups=0(root)
Контейнер пишет с теми правами, от которых запущен его процесс.
$ id
uid=1000(bozaro) gid=1000(bozaro)
$ docker run --rm --volume $(pwd):/workspace alpine \
touch /workspace/file.txt
$ ls -al file.txt
-rw-r--r-- 1 root root 0 июл 9 14:33 file.txt
$ vid=$(docker volume create)
$ echo ${vid}
f122409a44bd69485a02f1887b76fbc37936cd8bc387443194a1c9903057d448
$ docker run --rm --volume ${vid}:/workspace alpine \
ls /workspace
$ docker run --rm --volume ${vid}:/workspace alpine \
touch /workspace/file.txt
$ docker run --rm --volume ${vid}:/workspace alpine \
ls /workspace
file.txt
$ docker volume rm ${vid}
f122409a44bd69485a02f1887b76fbc37936cd8bc387443194a1c9903057d448
Создание VOLUME может быть прописано в метаданных Docker-образа, например:
FROM ubuntu:18.04
VOLUME /workspace
Обычно, такие VOLUME удаляются при удалении контейнера. Но иногда этого не происходит и они "подвисают".
Не подключаясь к контейнеру, можно скопировать всё его содержимое в TAR-архив:
$ container=$(docker run --rm --detach \
alpine:latest sleep 600)
$ docker export ${container} > alpine.tar
Так же можно копировать отдельные файлы из контейнера:
$ docker cp ${container}:/etc/ etc/
$ docker cp ${container}:/etc/hostname hostname
$ docker cp ${container}:/etc/ - > etc.tar
И в контейнер:
$ docker cp etc/ ${container}:/etc/
$ docker cp hostname ${container}:/etc/hostname
$ docker cp - ${container}:/etc/ < etc.tar
Ничто не мешает подключиться к контейнеру:
$ docker exec ${container} ps
PID USER TIME COMMAND
1 root 0:00 sleep 600
6 root 0:00 ps
$ docker exec -it ${container} /bin/sh
/ # ps aux
PID USER TIME COMMAND
1 root 0:00 sleep 600
11 root 0:00 /bin/sh
16 root 0:00 ps aux
/ # exit
$ docker run alpine/helm version
version.BuildInfo{Version:"v3.2.4", GitCommit:...
$ # helm version
$ docker run alpine/helm
The Kubernetes package manager
Common actions for Helm:
- helm search: search for charts
...
$ # helm --help
Если COMMAND ARG...
не указан, то он считается равным Cmd
.
Выполяется команда, полученная конкатенацией Entrypoint
и COMMAND ARG...
.
image | Entrypoint | Cmd |
---|---|---|
alpine |
|
|
alpine/helm |
|
|
$ docker inspect alpine/helm | jq -c ".[0].Config.Entrypoint"
["helm"]
$ docker inspect alpine/helm | jq -c ".[0].Config.Cmd"
["--help"]
Выполнится команда COMMAND ARG...
с учетом поиска в PATH
$ # /bin/sh -c whoami
$ docker run --entrypoint=/bin/sh alpine/helm -c whoami
root
$ docker run --entrypoint=/bin/ps alpine/helm
PID USER TIME COMMAND
1 root 0:00 /bin/ps
$ docker run --entrypoint=ps alpine/helm
PID USER TIME COMMAND
1 root 0:00 /bin/ps
Выполнится команда COMMAND ARG...
с учетом поиска в PATH
$ docker run --entrypoint="" alpine/helm whoami
root
$ docker run --entrypoint="" alpine/helm /bin/ps
PID USER TIME COMMAND
1 root 0:00 /bin/ps
$ docker run --entrypoint="" alpine/helm ps
PID USER TIME COMMAND
1 root 0:00 /bin/ps
Контейнер может содержать метки (LABEL).
Пример Dockerfile:
FROM ubuntu:18.04
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
Посмотреть метаданные контейнера/образа можно командой вида:
$ docker build -t test .
$ docker inspect test | jq ".[0].Config.Labels"
{
"com.example.label-with-value": "foo",
"com.example.vendor": "ACME Incorporated",
"version": "1.0"
}
Или через UI от Docker Registry
$ id=$(docker run --detach docker/whalesay cowsay boo)
$ sleep 5
$ docker inspect ${id} | jq ".[0].State.Status"
"exited"
$ docker logs ${id}
_____
< boo >
-----
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
$ docker logs --timestamps ${id}
2020-07-09T12:35:19.788330077Z _____
2020-07-09T12:35:19.788348669Z < boo >
2020-07-09T12:35:19.788354027Z -----
2020-07-09T12:35:19.788356697Z \
2020-07-09T12:35:19.788358973Z \
2020-07-09T12:35:19.788361128Z \
2020-07-09T12:35:19.788363290Z ## .
2020-07-09T12:35:19.788365599Z ## ## ## ==
2020-07-09T12:35:19.788367782Z ## ## ## ## ===
2020-07-09T12:35:19.788369934Z /""""""""""""""""___/ ===
2020-07-09T12:35:19.788372305Z ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
2020-07-09T12:35:19.788374442Z \______ o __/
2020-07-09T12:35:19.788376591Z \ \ __/
2020-07-09T12:35:19.788378853Z \____\______/
$ sudo cat /var/lib/docker/containers/${id}/${id}-json.log
{"log":" _____ \n","stream":"stdout","time":"2020-07-09T12:35:19.788330077Z"}
{"log":"\u003c boo \u003e\n","stream":"stdout","time":"2020-07-09T12:35:19.788348669Z"}
{"log":" ----- \n","stream":"stdout","time":"2020-07-09T12:35:19.788354027Z"}
{"log":" \\\n","stream":"stdout","time":"2020-07-09T12:35:19.788356697Z"}
{"log":" \\\n","stream":"stdout","time":"2020-07-09T12:35:19.788358973Z"}
{"log":" \\ \n","stream":"stdout","time":"2020-07-09T12:35:19.788361128Z"}
{"log":" ## . \n","stream":"stdout","time":"2020-07-09T12:35:19.78836329Z"}
{"log":" ## ## ## == \n","stream":"stdout","time":"2020-07-09T12:35:19.788365599Z"}
{"log":" ## ## ## ## === \n","stream":"stdout","time":"2020-07-09T12:35:19.788367782Z"}
{"log":" /\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"___/ === \n","stream":"stdout","time":"2020-07-09T12:35:19.788369934Z"}
{"log":" ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~ \n","stream":"stdout","time":"2020-07-09T12:35:19.788372305Z"}
{"log":" \\______ o __/ \n","stream":"stdout","time":"2020-07-09T12:35:19.788374442Z"}
{"log":" \\ \\ __/ \n","stream":"stdout","time":"2020-07-09T12:35:19.788376591Z"}
{"log":" \\____\\______/ \n","stream":"stdout","time":"2020-07-09T12:35:19.788378853Z"}
$ docker rm ${id}
По-умолчанию Docker не ротирует логи.
Из-за этого логи могут занять всё доступное место на диске Docker
# Use the official image as a parent image.
FROM node:current-slim
# Set the working directory.
WORKDIR /usr/src/app
# Copy the file from your host to your current location.
COPY package.json .
# Run the command inside your image filesystem.
RUN npm install
# Inform Docker that the container is listening on the specified
# port at runtime.
EXPOSE 8080
# Run the specified command within the container.
CMD [ "npm", "start" ]
# Copy the rest of your app's source code from your host to your
# image filesystem.
COPY . .
При каждом изменении внутренней файловой системы во время сборки контейнера будет создаваться новый слой (LAYER).
Слой содержит внутри изменения файловой системы:
Смена прав доступа равноценна полной перезаписи файла.
FROM ubuntu:18.04
LABEL com.joom.retention.maxDays=-1
ARG KUBE_VERSION=1.17.2
RUN apt -y update && apt -y install curl nginx
RUN curl -f -s -o /usr/local/bin/kubectl ... && \
chmod +x /usr/local/bin/kubectl && \
kubectl version --client
ADD default /etc/nginx/sites-available/default
ADD log-read.sh /opt/
RUN chmod +x /opt/log-read.sh
CMD ["/bin/bash", "-xc", "/opt/log-read.sh"]
docker image ls test
REPOSITORY TAG IMAGE ID CREATED SIZE
test latest 1c393d55d51c 4 minutes ago 206MB
При этом в docker registry размер того же образа будет 86.81MB.
Это вызвано тем, что docker image ls
и docker save
не используют сжание слоёв. При этом
внутри Docker Registry слои хранятся пожатые gzip-ом.
Это имеет забавное следствие: слои сжимаются на этапе docker push
, из-за этого заливка образов может
упираться в процессор, а не в сеть.
Так же важно заметить, что зачастую сумма размеров образов на равна общему размеру образов за счет переиспользования слоёв.