docker
记录 docker 的使用,包含 docker 常用命令和 Dockerfile 的编写。目前已经成功使用 dockerfile 发布了第一个应用rzero/pal
安装¶
ubuntu: Install Docker Engine on Ubuntu | Docker Docs
docker 命令行¶
container 相关¶
docker run
-it
:交互式-d
:启动后进入后台--rm
:运行后删除--name
-p
:映射端口,多个端口重复多次-p-v src:dst
:bind mount
删除容器,-f
用于删除正在运行的容器
查看容器输出,-f
跟踪输出
容器运行后,貌似不能修改映射端口和路径。可以通过 update 修改 cpu,内存等限制。 更新容器 restart policy
其它 指定用户运行
restart¶
- no
- Don't automatically restart the container. (Default)
on-failure[:max-retries]
- Restart the container if it exits due to an error, which manifests as a non-zero exit code. Optionally, limit the number of times the Docker daemon attempts to restart the container using the :max-retries option. The on-failure policy only prompts a restart if the container exits with a failure. It doesn't restart the container if the daemon restarts.
- always
- Always restart the container if it stops. If it's manually stopped, it's restarted only when Docker daemon restarts or the container itself is manually restarted.
- unless-stopped
- Similar to always, except that when the container is stopped (manually or otherwise), it isn't restarted even after Docker daemon restarts.
覆盖 Entrypoint¶
对于那些指定了 entrypoint 为特定程序,如 python 的容易非常有用,可以用于上去维修。
应用场景:如果容器在反复重启,导致无法 exec 上去。此时就需要使用镜像重新 docker run,然后修改 entrypoint 避免再次失败重启。
images 相关¶
重命名 image
save/load vs export/import vs commit¶
总结
docker save/load
:适用于备份和迁移一个或多个镜像,在不同的 Docker 主机之间传输。docker export/import
:适用于备份容器的文件系统,不包括完整的镜像元数据和历史记录。docker commit
:适用于创建基于容器当前状态的新镜像,包含新的一层 layer
save/load
将一个或多个镜像打包成 tar 归档文件,用于备份和传输镜像。 输出
docker save --output busybox.tar busybox # 输出到tar文件
docker save -o ubuntu.tar ubuntu:lucid ubuntu:saucy # 选择多个tag
docker save myimage:latest | gzip > myimage_latest.tar.gz # 输出到标准输出并使用gzip压缩
docker save myimage:latest | zstd > myimage_latest.tar.gz # 输出到标准输出并使用gzip压缩
导入
export/import
将容器的文件系统导出为 tar 文件,但不包含镜像的元数据和历史记录。
docker export -o container_filesystem.tar container_id
docker import container_filesystem.tar new_image_name:new_tag
commit
将容器目前的更改保存为新的一个 layer,从而基于该新镜像创建其它容器
docker commit nginx_base hello_world_nginx # 保存为hello_world_nginx镜像
docker commit --author amit.sharma@sentinelone.com --message 'this is a basic nginx image' nginx_base authored # 添加author, message信息
可以通过--change
修改原本容器的一些配置
- CMD
- ENTRYPOINT
- ENV
- EXPOSE
- USER
- VOLUME
- WORKDIR
example
docker run --entrypoint bash --name test --gpus '"device=0"' -u 0:0 -it ghcr.io/k4yt3x/video2x:5.0.0-beta6
docker commit --author yuanfuya@qq.com --message 'fix interpolate parameter' --change='Entrypoint ["/usr/bin/python3.8", "-m", "video2x"]' test video2x:5.0.0-beta6.2
rename¶
docker compose¶
升级镜像¶
dockerfile¶
创建 Dockerfile,经常遇到因为某一步错误,导致反复 docker build。其实可以先创建一个基础环境,然后进入环境配置一遍,成功后再写 dockerfile。
先如下搭建一个基础环境
然后进入项目,手动安装剩余依赖,直到测试能够运行
最后完善 Dockerfile
使用 entrypoint.sh 脚本¶
使用 entrypoint 脚本可以实现根据用户运行容器时指定的环境变量,设置用户 uid,gid,从而保证容器和 host 文件权限正确。
#!/bin/bash
PUID=${PUID:-1000}
PGID=${PGID:-1000}
if [ `id -u abc` -ne $PUID ]; then
usermod -u $PUID myuser
fi
if [ `id -g abc` -ne $PGID ]; then
groupmod -g $PGID abc
fi
chown -R abc:abc /parse-and-link
if [ -n "$JELLYFIN_URL" ] && [ -n "$JELLYFIN_API_KEY" ] ; then
echo "Jellyfin URL is set to $JELLYFIN_URL"
su abc -c "python3 run_config.py -c /config.json -m -j $JELLYFIN_URL -k $JELLYFIN_API_KEY"
else
su abc -c "python3 run_config.py -c /config.json -m"
fi
其它小 tips¶
测试版命令
发布版命令
docker run -d --name pal --restart unless-stopped \
-e JELLYFIN_URL="xxxxx" \
-e JELLYFIN_API_KEY="xxxxx" \
-v ./config/example.docker.json:/config.json \
rzero/pal:v1.0
- 使用
.dockerignore
文件,否则每次修改 Dockerfile,COPY 之后的步骤就都不能复用了
发布到 dockerhub¶
docker 实验¶
软硬链接¶
总结
- 软链接需要使用相对路径,并且 src 和 dst(链接)最长相同路径的目录,必须同时存在于 docker 和 host
- 硬链接没有任何要求,打上链接的一刻,任何地方均能访问到该文件
实验: host:
➜ pwd
/home/yfy/scripts/test/mnt
➜ tree -L 4
.
├── Disk1
│ ├── links
│ │ └── Movie
│ │ ├── aa.mp4 -> ../../Movie/a.mp4
│ │ ├── a.mp4 -> /home/yfy/scripts/test/mnt/Disk1/Movie/a.mp4
│ │ └── b.mp4 # 硬链接
│ └── Movie
│ └── a.mp4 # 原始文件
├── Disk2
├── outfile -> ../../outfile # 软链接到docker中看不到的目录文件
└── outfile-hl # 硬链接
5 directories, 7 files
docker:
ubuntu@dfc03804864c ➜ pwd
/workspace/mnt
ubuntu@dfc03804864c ➜ tree -L 4
.
|-- Disk1
| |-- Movie
| | `-- a.mp4
| `-- links
| `-- Movie
| |-- a.mp4 -> /home/yfy/scripts/test/mnt/Disk1/Movie/a.mp4 (无法访问)
| |-- aa.mp4 -> ../Movie/a.mp4 (无法访问)
| |-- aaa.mp4 -> ../../Movie/a.mp4
| `-- b.mp4
|-- Disk2
|-- outfile -> ../../outfile (无法访问)
`-- outfile-hl (无法访问)
5 directories, 7 files
在 docker 和 host 中查看 outfile-hl 的 inode 可以看到和源文件 outfile 是相同的
➜ ls -i ../../outfile
1091603 -rw-rw-r-- 2 yfy yfy 0 12月 9 16:57 ../../outfile
➜ ls -i outfile-hl
1091603 -rw-rw-r-- 2 yfy yfy 0 12月 9 16:57 outfile-hl
gpu¶
Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error running hook #0: error running hook: exit status 1, stdout: , stderr: Auto-detected mode as 'legacy'
nvidia-container-cli: initialization error: nvml error: driver/library version mismatch: unknown
Error: failed to start containers: jellyfin
[Sat Apr 13 23:38:47 2024] NVRM: API mismatch: the client has the version 535.171.04, but
NVRM: this kernel module has the version 535.161.07. Please
NVRM: make sure that this kernel module and all NVIDIA driver
NVRM: components have the same version.
nvidia-container-toolkit¶
nvidia runtime
nvidia-container-runtime 已经被 nvidia-container-toolkit 替代了: NVIDIA/nvidia-container-runtime: NVIDIA container runtime (github.com)
安装教程
Installing the NVIDIA Container Toolkit — NVIDIA Container Toolkit 1.16.0 documentation
Configure the container runtime by using the nvidia-ctk
command: