Astro's 踩坑记录

Docker 笔记

字数统计: 1.9k阅读时长: 7 min
2022/09/04

Dcoker是什么

容器化技术 直接运行在操作系统上(宿主机内核中)没有虚拟硬件 内核级别虚拟化 轻便 每个容器间互相隔离 各有自己的文件系统 通过镜像生成容器

所有docker镜像都是只读,在镜像启动时加载一个新的可写层至镜像层顶部,即为容器层。
8f136c933dba31d015eca1c9526d6457.jpeg
4e473c94c8e44c6ea223b214642cdb35.png

Docker入门命令

命令概览

所有命令可在Docker命令官方文档中查询

1
2
#一条通用原则
docker cmd --help # 查看cmd支持的常用命令 完整版在官方文档搜索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#关于镜像
docker rmi xxx # 删除镜像(i->images)
docker images # 查看所有镜像
docker history 镜像id #查看镜像创建的历史及步骤
docker search xxx # 查询镜像
docker push #发布镜像(docker hub 阿里云)
#关于容器
docker info #显示docker系统信息 包括镜像、容器数量
docker run 镜像id [cmd] # 生成容器并运行命令
docker ps # 查看所有容器
docker top 容器id # 查看容器内进程
docker inspect 容器id # 查看容器所有信息 包括容器内的默认环境...
docker rm xxx # 删除容器
docker start/restart/stop/kill 容器id #开启/重启/结束/关闭 容器
docker logs #查看log文件
docker stats #查看所有容器的cpu占用等信息
docker commmit -m="commited_information" -a="author_name" 容器id name:tag #保存容器为新镜像

进入容器后

1
2
exit         # 退出并关闭容器
ctrl+p+q # 退出容器 保持后台运行

通常将容器放在后台运行,此时如果需要进入当前正在运行的容器

1
2
3
docker exec -it 容器id 进入后执行的命令   #(通常执行bash)  
#或
docker attach 容器id #如果容器正在执行文件或有持续输出,则持续显示输出信息

关于宿主机与容器的文件交换

1
2
3
4
5
6
7
# 1. 手动从容器拷贝文件到主机(只要容器在数据就在,无论是否运行,即docker ps -a存在即可):
# 先进入容器
docker attach 容器id
#然后复制文件
docker cp 容器id:/path/of/docker /path/of/linux
# 2. 在创建容器时挂载文件到容器内,实现双向同步
docker run -it -v /path/of/local:/path/of/docker 镜像名称 bash

数据共享(目录挂载)时,将容器内的目录挂载到linux上,以实现容器的持久化和同步操作。容器之间的数据也可以共享。
可通过以下方式查看挂载信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker inspect 容器id
[
...
"Mounts": [
{
"Type": "bind",
"Source": "/home/hjj",
"Destination": "/tmp",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
...
]

-v后宿主机路径与容器路径会绑定,若本机不存在此路径则新建,文件双向绑定同步,即使exit退出容器只要镜像还在(docker ps -a)即可在本地修改文件并在容器中同步。即使删除容器,改变的数据文件已存在本地,所以不会丢失。
通过以下命令重新进入容器

1
2
docker start  容器id
docker attatch 容器id

文件挂载的两种方式

匿名挂载
1
2
-v 容器内路径
docker volume ls # 查看所有卷,由于-v之后为给定本机路径,因此输出的 VOLUME NAME 为英文+数子的长字符串
具名挂载 (常用)
1
2
-v name:容器内路径  # name中不包含/,否则表示本机路径 
docker volume inspect name #查看卷
1
2
-v /path/of/local:容器内路径 #表示指定路径挂载
# 未指定目录的情况下挂载在本机/var/lib/docker

容器内路径后可通过 :ro rw 来改变读写权限,表示只读/只写,ro表示容器中此路径只能通过宿主机操作

Dockerfile

Dockerfile官方说明
用于构建docker的构建文件,为命令脚本,通过docker build构建成为镜像。很多官方镜像都是基础包(FROM scratch),缺乏很多功能如vim,因此通常自己制作镜像。
面向开发,通常用于发布项目/做镜像,镜像已逐渐成为企业交付的标准。DockerImages通过DockerFile生成的镜像 最终发布和运行的产品。
Dockerfile中关键字建议大写,指令小写,用 # 注释。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FROM                     # 基础镜像 从此开始构建
MAINTAINER # 维护者 姓名➕邮箱
RUN # 构建镜像时需要运行的命令
ADD # 可将压缩包自动解压到容器指定路径下 ADD xxx.tgz /path,也可以指定url/路径
# 只能将dockerfile所在的路径及更深层次的文件/文件夹加入,不可加入 ../xxx
COPY # 类似ADD 将文件拷贝到镜像中
WORKDIR # 镜像的工作目录 可多次指定,表示在之前WORKDIR之后
# 如 WORKDIR /a \n WORKDIR b,则后面位于/a/b路径下
VOLUME # 挂载的目录
EXPOSE # 同-p 暴露端口
CMD # 指定容器启动时运行的命令 只有最后一个会生效,可被替代 可通过&&执行多个命令
ENTRYPOINT # 指定容器启动时运行的命令 可以追加
ONBUILD # 当构建一个被继承的dockerfile时,ONBUILD就会运行

ENV # 构建时设置环境变量

通过以下命令创建镜像。注意最后的 . 表示当前路径不要遗漏。

1
docker build -f dockerfile_name -t 镜像名[:tag]  .

若命名为Dockerfile可省去-f dockerfile_name的指令。

Dockerfile中CMD与ENTRYPOINT区别

对于dockerfile创建的镜像,可通过以下命令来指定运行容器后需要执行的命令:

1
docker run 镜像id [cmd] 

此cmd会覆盖Dockefile中CMD指定的命令,而对于ENTRYPOINT指定的命令,cmd会追加在命令后执行,不会忽略。

ADD与COPY的区别

二者区别不大,都可以从主机上将资源复制或加入到镜像中,都是在构建镜像过程中完成。
COPY支持从远程URL获取资源,而ADD不行,后者更擅长读取本地tar文件并解压。
在用途相同时开发者更推荐前者

镜像发布

可将打包好的镜像发布至 docker官网镜像网站 供他人下载,也可以在此寻找别人打包好的镜像。
在提交到hub之前必须给镜像加上tag:

1
docker tag SOURCE_IMAGE[:TAG] hub_username/TARGET_IMAGE[:TAG]

hub_username为docker账号的用户名,且提交前必须在镜像前加上此字段,然后:

1
docker push hub_username/TARGET_IMAGE[:TAG]

即可在镜像网站中登陆查看到。
也可以推送至阿里云(收费托管)

个人常用命令

从tensorflow官网拉取镜像运行tf-GPU(若GPU设备足够(算力(Compute Capability)大于5.2)可使用NVIDIA-docker官网的TensorFlow镜像):

1
2
docker run --gpus all -it --rm  -v $PWD:/tmp -w /tmp tensorflow/tensorflow:latest-gpu bash
ocker run --gpus all -it --rm -v $PWD/ResCu:/ResCu -w /ResCu tensorflow/tensorflow:2.4.1-gpu bash

需要手动安装scipy/matplotlib/vim等库/软件

1
2
3
4
5
6
7
docker ps -a        #正在以及历史运行的容器
docker ps -a -n=1 #只显示一个
docker ps -aq -n=1 #只显示一个并只显示id

docker rm -f $(docker ps -aq) #查询所有容器id并逐个删除容器

docker logs -tf -tail n #带时间戳查看最新n个log

踩坑记录

1
docker run -d 镜像名  # 对于某些镜像,在docker ps时不会找到,因为后台运行时必须要有一个前台进程  否则docker发现没有应用会自动停止

暂时未找到在Dockerfile中设置Nvidia GPU的办法,只能通过以下方法调用,较为麻烦。找了一天没找到解决办法,留个坑看未来是否能解决。

1
2
3
docker run --gpus all .....
# 或是
docker run --runtime=nvidia ... #需要在/etc/docker/daemon.json中加入runtime配置信息并重启docker才行
CATALOG
  1. 1. Dcoker是什么
    1. 1.0.1. 容器化技术 直接运行在操作系统上(宿主机内核中)没有虚拟硬件 内核级别虚拟化 轻便 每个容器间互相隔离 各有自己的文件系统 通过镜像生成容器
  • 2. Docker入门命令
    1. 2.1. 命令概览
    2. 2.2. 关于宿主机与容器的文件交换
      1. 2.2.1. 文件挂载的两种方式
        1. 2.2.1.1. 匿名挂载
        2. 2.2.1.2. 具名挂载 (常用)
    3. 2.3. Dockerfile
      1. 2.3.1. Dockerfile中CMD与ENTRYPOINT区别
      2. 2.3.2. ADD与COPY的区别
    4. 2.4. 镜像发布
    5. 2.5. 个人常用命令
    6. 2.6. 踩坑记录