理解 image 和 container 的区别
image 即镜像,只读不可写,可以理解为「橡皮泥」生产线生产「橡皮泥」的地方;
container 即容器,可读可写,可以理解为从「橡皮泥」生产线拿到一块「橡皮泥」,可以用这块橡皮泥做各种事情。
当然,我们可以制作镜像,可以抓取镜像。而一般我们说使用docker的时候,常常是使用容器。简单来说是,先抓取或者载入镜像,通过镜像创建一个容器,然后在容器内做各种各样的操作。
抓取镜像和使用docker
docker 环境部署完成后,本地是没有镜像的,自然也没有容器。如果我们要使用 docker,那么需要先创建一个镜像或者说可以直接抓取一个云端的基础镜像
查看有什么镜像

随后可以使用镜像,从云端抓取 ubuntu 镜像并以交互模式进入,-i
表示交互模式,-t
表示创建一个 tty

可以在另外一个窗口查看有什么容器(新开一个 cmd 窗口)

进行一些操作
(此时在容器环境中,容器ID:6070f504a4fb)
简单安装 ncbi-blast+
apt-get update
apt-get install -y ncbi-blast+
当然还可以做很多其他环境部署工作,完成后可以退出或者不退出
导出容器为镜像
有两种方式可以实现
1. 使用 commit 和 save
比较简单,在docker环境外,容器ID即为上述ID(我们可以对即将创建的新镜像命名为 hello,版本是 1.0)
docker commit 6070f504a4fb helloworld:1.0
随后可以导出
docker save helloworld:1.0 > helloworld.tar
到新的电脑,使用 docker load 即可(注意 load 模式无法执行新的镜像名字,这在commit的时候已经指定)
docker load < helloworld.tar
2. 直接使用 export
对于任何一个容器,可以直接 export。此处无法指定镜像名字
docker export 6070f504a4fb > byebyeworld.tar
如此在新的设备上,使用docker import
(可以补充执行镜像名字为 goodbye,版本为 1.0)
docker import byebyeworld.tar goodbye:1.0
镜像文件可以压缩
直接在 wsl 中使用 xz 可以实现极限压缩
进一步理解容器
逻辑上,我们基于镜像创建了一个容器,对容器的所有操作和改造都被完整记录。退出容器,那么容器和他的修改仍然存在,比如前面我们安装的blast仍然可用。比如,在容器中
可以在外部看到,容器仍然存留

容器属于 exited
状态。我们当然可以删了他
我们也可以重新启动并进入这个容器
docker start 6070f504a4fb
docker exec -it 6070f504a4fb bash
进一步理解基于镜像创建容器
每一次,我们使用 docker run image
都会新建一个容器
如此容器就会不断积累。我们可以通过下述命令查看所有容器状态
如果我们想删除某个容器,那么可以使用
但是,如果容器仍然在运行(也可以是在后台运行,比如做了一些网站容器,比如Rstudio网页版)。那么可以用
如此来删除该容器。
如果我们想删除某个镜像,那么需要使用
注意到,如果基于这个镜像创建的容器还在本机存在(无论是否在运行),那么需要删掉这些相关容器,最后才能成功删除镜像。
自然有些时候,我们基于镜像创建容器并执行一些任务后,并不希望保留容器,那么当我们执行docker run
或者类似的docker exec
的时候,可以补充参数--rm
。如此会在退出容器时,自动删除容器。
docker run -it --rm ubuntu
映射本地目录为 docker 容器目录
很多时候,我们需要让docker读取和写入本地文件。下述命令可以映射当前工作目录为镜像中的/scauclass
目录,同时,进去镜像时,自动-w
切换到该目录
docker run -v %cd%:/scauclass -w /scauclass -it ubuntu
docker run -v $(pwd):/scauclass -w /scauclass -it ubuntu
注意到,如此操作/scauclass
中写入写出或者其他任何操作都会同步影响到本地文件。
提交镜像到 Docker Hub
提交镜像到 Docker Hub,可以方便其他人使用,甚至可用于其他常用容器软件,如 Singularity 等
在命令行上,先docker login
注意,对于要提交的其镜像名字,比如带有符合「账户/镜像」这个格式。我的账户名字为「cjchen」,故对已有镜像进行一次重命名,补充 cjchen,如此才可正常提交
docker tag tbtoolszone:2.0 cjchen/tbtoolszone:2.0
docker push cjchen/tbtoolszone:2.0

如此,就提交上去了。后续可以使用如docker pull
或者singularity pull
等来直接使用

抓取镜像之后测试(似乎会自动完成本地路径映射,无需继续 -v)
docker pull cjchen/tbtoolszone:2.0
docker run -it --rm cjchen/tbtoolszone:2.0
seqkit
exit
关于 Dockerfile
逻辑上,交互式构建 docker image 期间,记录所有执行的命令,整理一下,即可写成 Dockerfile,方便后续更快部署,同时也可以获得更为轻量的容器。