Docker is an open source platform for building, deploying, and managing containerized applications.
Docker 参考资料 https://www.docker.com/ https://www.docker.org.cn/ Developers Love Docker. Businesses Trust It. Build safer, share wider, run faster: New updates to our product subscriptions. https://docs.microsoft.com/en-us/dotnet/architecture/microservices/container-docker-introduction/docker-defined https://www.ibm.com/cloud/learn/docker 官方镜像中心 https://hub.docker.com/ 网易镜像中心 https://c.163yun.com/hub#/home
Docker能把环境打包,实现运行环境的快速、方便迁移。
虚拟化软件运行环境,以最小的代价换取最大的资源。docker 直接利用宿主机的内容加上 docker engine 就能运行容器,极大的节省了性能开销。docker 是秒级,虚拟机是分钟级。
docker 中的三大概念: 仓库(repository):Docker hub,存放在镜像的地方,可配置国内镜像加速下载。 镜像(image):是一个模块,里面是打包的环境,可基于此模板运行处多个容器。 容器(container):镜像运行后会记录数据和状态,叫容器。通过镜像创建的独立运行的一个或一组应用。 Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。 docker三大功能:构建(build)、运输(ship)、运行(run),只需要记下这三大功能就可以了。 Docker有五个命名空间:进程、网络、挂载、宿主和共享内存。这个用来排错。
本文尝试在Ubuntu 20.04 和 CentOS7.9上分安装最新的 docker 版本。
本文使用 Ubuntu 20.04 作为宿主机,安装 docker 最新版。
全新的 桌面版 Ubuntu 20.04.3 LTS (GNU/Linux 5.11.0-34-generic x86_64),virtualBox。 仅仅安装最基本的软件 install: - openssh-server - net-tools: ifconfig #前两个local shell安装 - vim #其余的可以ssh登录后安装 - htop - tmux - curl #后来装的 内核版本: $ uname -r 5.11.0-34-generic
如果snap安装过docker,先卸载。 $ sudo snap remove docker docker removed $ docker --version -bash: /snap/bin/docker: No such file or directory 以下为全新安装。 1. 替换为国内的源 $ sudo mv /etc/apt/sources.list /etc/apt/sources.list-backup $ sudo vim /etc/apt/sources.list #清华源 https://mirror.tuna.tsinghua.edu.cn/help/ubuntu/ # 可以把偶数行的 -src 注释掉,如果不看源码的话。会更快。 deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse 2. 安装 $ sudo apt update $ sudo apt upgrade #是否有必要呢? $ sudo apt install docker.io $ docker --version Docker version 20.10.7, build 20.10.7-0ubuntu1~18.04.1 为什么比昨天安装的落后一个版本号20.10.8呢? (1) 查看版本号 $ whereis docker docker: /usr/bin/docker /etc/docker /usr/share/docker.io /usr/share/man/man1/docker.1.gz $ which docker /usr/bin/docker $ ls -lth /usr/bin/docker -rwxr-xr-x 1 root root 69M Aug 5 03:22 /usr/bin/docker 重启的方式: $ sudo service docker status #active 查看启动的位置: $ ps -aux | grep docker root 19330 0.0 4.4 725440 89884 ? Ssl 19:48 0:01 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock wangjl 19481 0.0 0.0 17672 740 pts/1 S+ 20:09 0:00 grep --color=auto docker (2) 通过将用户添加到docker用户组可以将sudo去掉 https://linuxhandbook.com/docker-permission-denied/ $ sudo groupadd docker #添加docker用户组 $ sudo gpasswd -a $USER docker #将登陆用户加入到docker用户组中 Adding user wangjl to group docker $ newgrp docker #更新用户组 $ groups #或者 id 命令 查看当前用户所在的组 docker adm cdrom sudo dip plugdev lpadmin lxd sambashare wangjl 把待启动锁改为 docker 组 $ ls -lth /var/run/docker.sock srw-rw---- 1 root root 0 Sep 14 11:30 /var/run/docker.sock $ sudo chown root:docker /var/run/docker.sock $ ls -lth /var/run/docker.sock srw-rw---- 1 root docker 0 Sep 14 11:30 /var/run/docker.sock (3) docker 镜像保存的位置 $ docker info ... Storage Driver: overlay2 Docker Root Dir: /var/lib/docker ... $ sudo ls -lth /var/lib/docker total 48K drwx------ 2 root root 4.0K Sep 14 19:48 tmp drwx-----x 3 root root 4.0K Sep 14 19:48 overlay2 drwx-----x 2 root root 4.0K Sep 14 19:48 volumes drwx------ 2 root root 4.0K Sep 14 19:48 runtimes -rwxr-xr-x 1 root root 1.5K Sep 14 19:39 nuke-graph-directory.sh drwx--x--x 4 root root 4.0K Sep 14 19:16 buildkit drwx------ 2 root root 4.0K Sep 14 19:16 swarm drwxr-x--- 3 root root 4.0K Sep 14 19:16 network drwx------ 2 root root 4.0K Sep 14 19:16 trust drwx------ 3 root root 4.0K Sep 14 19:16 image drwx------ 4 root root 4.0K Sep 14 19:16 plugins drwx-----x 2 root root 4.0K Sep 14 19:16 containers 拉取一个轻量级镜像: 227M $ docker pull hub.c.163.com/library/node:slim $ docker tag hub.c.163.com/library/node:slim node:slim $ docker rmi hub.c.163.com/library/node:slim $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE node slim 914ef9e2ccb0 4 years ago 227MB (4) 挂载一块硬盘到 /data 下。 必须先把虚拟机关机才能添加硬盘。 $ sudo shutdown -t now 右击-设置-存储,右击sata-创建新的虚拟硬盘-创建一个10G动态分配大小的磁盘,文件名是 NewVirtualDisk1.vdi 再次双击启动虚拟机。 1)查看新磁盘名字 $ sudo fdisk -l Device Boot Start End Sectors Size Id Type /dev/sda1 * 2048 1050623 1048576 512M b W95 FAT32 /dev/sda2 1052670 20969471 19916802 9.5G 5 Extended /dev/sda5 1052672 20969471 19916800 9.5G 83 Linux Disk /dev/sdb: 10 GiB, 10737418240 bytes, 20971520 sectors Disk model: VBOX HARDDISK Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes 2)给新加的硬盘分区 要有root权限 $ sudo fdisk /dev/sdb 键入 m,可看到帮助信息 command (m for help):m 增加新分区 command (m for help):n 选择基本分区,输入: p 建一个分区 Partition number(1-4):1 回车 First cylinder (1-15908,default 1):Enter 写入并退出 command (m for help):w 3)用 ext4格式对/dev/sdb1进入格式化 $ sudo mkfs.ext4 /dev/sdb1 4)创建新的挂载点 $ sudo mkdir /data2 5)将新磁盘分区挂载到 /work目录下 $ sudo mount -t ext4 /dev/sdb1 /data2 #后两个参数分别是硬件和挂载点 5)查看挂载 $ df -h 可以看到新加的硬盘: /dev/sdb1 9.8G 37M 9.3G 1% /data2 6)开机自动挂载 修改文件 $ sudo vim /etc/fstab 在最后一行加入: /dev/sdb1 /data2 ext4 errors=remount-ro 0 1 (5) 运行镜像 $ docker run -it --mount type=bind,source=/home/,target=/tmp02 --rm node:slim bash #ok root@b0180129ec0a:/# exit exit $ df -h | grep sd /dev/sda5 9.3G 6.4G 2.5G 73% / /dev/sda1 511M 4.0K 511M 1% /boot/efi /dev/sdb1 9.8G 37M 9.3G 1% /data2 $ docker run -it --mount type=bind,source=/data1,target=/tmp02 --rm node:slim bash root@05beaff3515e:/# exit exit 挂在 $HOME 以外的目录到docker,没有报错。 docker 包括服务端和客户端。 $ docker version Client: Version: 20.10.7 API version: 1.41 Go version: go1.13.8 Git commit: 20.10.7-0ubuntu1~18.04.1 Built: Wed Aug 4 22:43:25 2021 OS/Arch: linux/amd64 Context: default Experimental: true Server: Engine: Version: 20.10.7 API version: 1.41 (minimum version 1.12) Go version: go1.13.8 Git commit: 20.10.7-0ubuntu1~18.04.1 Built: Wed Aug 4 19:22:59 2021 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.5.2-0ubuntu1~18.04.2 GitCommit: runc: Version: 1.0.0~rc95-0ubuntu1~18.04.2 GitCommit: docker-init: Version: 0.19.0 GitCommit:
使用 snap 安装的docker只能挂载$HOME 下的目录,不能挂载/data等目录。
https://docs.docker.com/get-docker/ 1. snap 安装 $ sudo snap install docker docker 20.10.8 from Canonical✓ installed (1) 查看版本号 $ docker --version Docker version 20.10.8, build 3967b7d28e $ whereis docker docker: /snap/bin/docker.compose /snap/bin/docker /snap/bin/docker.help /snap/bin/docker.machine $ which docker /snap/bin/docker $ ls -lth /snap/bin/docker lrwxrwxrwx 1 root root 13 9月 14 11:30 /snap/bin/docker -> /usr/bin/snap $ /usr/bin/snap --version snap 2.51.3 snapd 2.51.3 series 16 ubuntu 20.04 kernel 5.11.0-34-generic $ /snap/bin/docker --version Docker version 20.10.8, build 3967b7d28e 重启的方式 $ sudo snap start docker Started. $ sudo snap services Service Startup Current Notes docker.dockerd enabled active - 查看启动的位置 $ ps -aux | grep docker root 7491 4.4 3.9 1348260 79800 ? Ssl 16:31 0:05 dockerd --group docker --exec-root=/run/snap.docker --data-root=/var/snap/docker/common/var-lib-docker --pidfile=/run/snap.docker/docker.pid --config-file=/var/snap/docker/1125/config/daemon.json root 7538 2.7 2.1 1203244 42736 ? Ssl 16:31 0:03 containerd --config /run/snap.docker/containerd/containerd.toml --log-level error wangjl 7738 0.0 0.0 17672 732 pts/1 S+ 16:33 0:00 grep --color=auto docker $ docker ps Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json": dial unix /var/run/docker.sock: connect: permission denied (2) 通过将用户添加到docker用户组可以将sudo去掉 https://linuxhandbook.com/docker-permission-denied/ $ sudo groupadd docker #添加docker用户组 $ sudo gpasswd -a $USER docker #将登陆用户加入到docker用户组中 Adding user wangjl to group docker $ newgrp docker #更新用户组 $ groups #或者 id 命令 查看当前用户所在的组 docker adm cdrom sudo dip plugdev lpadmin lxd sambashare wangjl 把待启动锁改为 docker 组 $ ls -lth /var/run/docker.sock srw-rw---- 1 root root 0 Sep 14 11:30 /var/run/docker.sock $ sudo chown root:docker /var/run/docker.sock $ ls -lth /var/run/docker.sock srw-rw---- 1 root docker 0 Sep 14 11:30 /var/run/docker.sock (3) docker 镜像保存位置 $ docker info ... Storage Driver: overlay2 Docker Root Dir: /var/snap/docker/common/var-lib-docker ... $ sudo ls -lth /var/snap/docker/common/var-lib-docker total 48K drwx------ 2 root root 4.0K Sep 14 16:31 tmp drwx--x--x 4 root root 4.0K Sep 14 16:31 buildkit drwx-----x 3 root root 4.0K Sep 14 16:31 overlay2 drwx------ 2 root root 4.0K Sep 14 16:31 swarm drwxr-x--- 3 root root 4.0K Sep 14 16:31 network drwx------ 2 root root 4.0K Sep 14 16:31 trust drwx------ 3 root root 4.0K Sep 14 16:31 image drwx-----x 2 root root 4.0K Sep 14 16:31 volumes drwx------ 4 root root 4.0K Sep 14 16:31 plugins drwx-----x 2 root root 4.0K Sep 14 16:31 containers drwx------ 2 root root 4.0K Sep 14 16:31 runtimes drwx--x--x 3 root root 4.0K Sep 14 16:31 containerd 拉取一个轻量级镜像: 227M $ docker pull hub.c.163.com/library/node:slim $ docker tag hub.c.163.com/library/node:slim node:slim $ docker rmi hub.c.163.com/library/node:slim $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE node slim 914ef9e2ccb0 4 years ago 227MB (4) 挂载一块硬盘到 /data 下。 见上文。 关闭虚拟机,添加虚拟盘。 开机,格式化, 挂载: $ sudo mkdir /data1 $ sudo mount -t ext4 /dev/sdb1 /data1 #后两个参数分别是硬件和挂载点 (5) 运行镜像 $ docker run -it --mount type=bind,source=/home/,target=/tmp02 --rm node:slim bash #ok root@7648f5a17624:/# exit exit $ df -h | grep sd /dev/sda5 9.3G 5.9G 3.0G 67% / /dev/sda1 511M 4.0K 511M 1% /boot/efi /dev/sdb1 9.8G 37M 9.3G 1% /data2 $ docker run -it --mount type=bind,source=/data2,target=/tmp02 --rm node:slim bash docker: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /data2. See 'docker run --help'. 这里报错了!不能挂载 $HOME 以外的目录。
1.查询老版本docker
$ rpm -qa|grep -i docker
如果有,删掉:
# rpm -e docker-1.13.1-75.git8633870.el7.centos.x86_64
# rpm -e docker-client-1.13.1-75.git8633870.el7.centos.x86_64
# rpm -e docker-common-1.13.1-75.git8633870.el7.centos.x86_64
2.安装docker(跳过)
$ sudo yum install -y docker
$ docker --version
Docker version 1.13.1, build 7d71120/1.13.1
很古老的版本! 不支持 mount
3.重新安装,按照官方文档 https://docs.docker.com/engine/install/centos/
$ sudo yum install -y yum-utils
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum install docker-ce docker-ce-cli containerd.io
根据提示,按两次y。
$ docker --version
Docker version 20.10.9, build c2ea9bc
这是最新版,可以用了。
4. 修改镜像地址,
$ sudo vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://uulfe4bd.mirror.aliyuncs.com"]
}
启动服务
$ sudo systemctl start docker
5. 解决权限
$ sudo groupadd docker #添加docker用户组
$ sudo gpasswd -a $USER docker #将登陆用户加入到docker用户组中
Adding user wangjl to group docker
$ newgrp docker #更新用户组
$ groups #或者 id 命令 查看当前用户所在的组
docker adm cdrom sudo dip plugdev lpadmin lxd sambashare wangjl
修改执行组为 docker
$ sudo chown root:docker /var/run/docker.sock
srw-rw---- 1 root docker 0 Oct 11 22:48 /var/run/docker.sock
6. nginx镜像使用实例
拉取镜像
$ docker pull nginx
查看版本号
$ docker run --rm -it nginx nginx -v
nginx version: nginx/1.21.3
查看配置文件
## docker run --rm -it nginx cat /etc/nginx/nginx.conf
$ docker run --rm -it nginx cat /etc/nginx/conf.d/default.conf
模仿 default.conf 文件写一个配置文件
$ cat nginx.config
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
# list files
autoindex on;
autoindex_exact_size on;
autoindex_localtime on;
}
}
启动容器:做文件挂载、端口映射。
$ docker run --rm -d -p 8080:80 \
--mount type=bind,source=/home/wangjl/,target=/usr/share/nginx/html/ \
--mount type=bind,source=$PWD/nginx.config,target=/etc/nginx/conf.d/default.conf \
nginx
检查状态
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
81d91430ec78 87a94228f133 "/docker-entrypoint.…" 50 seconds ago Up 49 seconds 0.0.0.0:8080->80/tcp, :::8080->80/tcp reverent_buck
打开浏览器,http://IP:8080
能看到文件列表。
如果无法访问,可能是防火墙。
$ sudo systemctl stop firewalld 关闭防火墙
默认 docker 都在根目录,可能随着时间的推移导致系统盘不够用。建议一开始就把docker数据切换到一个大硬盘,这样还能防止经常读写的系统盘坏掉而损失数据。
示例: 把默认的docker目录 /var/lib/docker 改为 /data/docker/lib/docker 。
查看版本
$ docker --version
Docker version 20.10.15, build fd82621
查看数据保存的位置
$ sudo docker info
Docker Root Dir: /var/lib/docker
Registry: https://index.docker.io/v1/
1. 停止docker服务。
$ sudo systemctl stop docker
或
$ sudo service docker stop
$ service docker status
2. 创建新的docker目录
执行命令df -h,找一个大的磁盘。 我在 /home目录下面建了 /home/docker/lib目录,执行的命令是:
## mkdir -p /home/docker/lib
$ sudo mkdir /data/docker
$ sudo mkdir /data/docker/lib
3. 迁移 /var/lib/docker 目录下面的文件到 /home/docker/lib:
## rsync -avz /var/lib/docker /home/docker/lib/
$ sudo rsync -avz /var/lib/docker /data/docker/lib/
实际位置从 /var/lib/docker 变为 /data/docker/lib/docker
耗时: 14:25-->
还有人用 -P 参数: rsync -avzP /var/lib/docker/ /data/lib/docker
4、(跳过该步骤。可能是老方案,不一定可用了) 配置 /etc/systemd/system/docker.service.d/devicemapper.conf
查看 devicemapper.conf 是否存在。如果不存在,就新建。
$ sudo mkdir -p /etc/systemd/system/docker.service.d/
$ sudo vim /etc/systemd/system/docker.service.d/devicemapper.conf
然后在 devicemapper.conf 写入:(同步的时候把父文件夹一并同步过来,实际上的目录应在 /home/docker/lib/docker )
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --graph=/data/docker/lib/docker
#ExecStart=/usr/bin/dockerd --graph=/home/docker/lib/docker
5. 修改配置目录
如果配置文件不存在,则新建一个。
$ cat /etc/docker/daemon.json
{
"data-root": "/data/docker/lib/docker"
}
(可选)添加国内的源:
$ cat /etc/docker/daemon.json
{
"data-root": "/data/docker/lib/docker",
"registry-mirrors": ["http://hub-mirror.c.163.com"]
}
或者 华中科技大学的源:
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
6. 重新启动 docker 服务
# sudo systemctl daemon-reload #加载配置文件
# sudo systemctl restart docker.service #重启服务
# sudo systemctl enable docker #允许开机启动
$ sudo service docker start
7. 配置核查
docker info 命令检查Docker 的根目录.它将被更改为 /home/docker/lib/docker
$ sudo docker info | grep Root
Docker Root Dir: /data/docker/lib/docker
8. 启动成功后,再确认之前的镜像还在:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
AAA/AAA v2 7331b8651bcc 27 hours ago 3.85GB
BBB/BBB v1 da4a80dd8424 28 hours ago 3.47GB
9、 确定容器没问题后删除 /var/lib/docker/ 目录中的文件。
$ sudo mv /var/lib/docker /var/lib/docker-can-delete #先重命名文件,放几周再删掉。
$ ls -lth /var/lib/ | grep docker
drwx--x---. 15 root root 200 May 10 14:04 docker-can-delete
drwxr-xr-x. 2 root root 6 May 6 13:42 docker-engine
(1)配置国内镜像加速
$ sudo vim /etc/docker/daemon.json
{
"registry-mirrors": [
"http://hub-mirror.c.163.com",
"https://registry.cn-hangzhou.aliyuncs.com"
]
}
$ sudo systemctl daemon-reload #重启守护进程
$ sudo systemctl restart docker
(2) 下载基本镜像
$ docker login -u 用户名
输入密码 # 登录后增大下载成功几率
$ docker pull ubuntu #下载镜像
$ docker pull nginx
(3)如果不确定镜像名字,可以先搜索
$ docker search ubuntu #搜索镜像
$ docker search seurat
$ docker search monocle
$ docker search rstudio
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
rocker/rstudio RStudio Server image 372 [OK]
2)如何获取tag编号呢?
https://www.jianshu.com/p/f974ec9e7937
$ curl -L -s 'https://registry.hub.docker.com/v2/repositories/library/hello-world/tags?page_size=1024' | jq '.results[]["name"]' | sed 's/\"//g' | sort -u
改成不另装软件的可行方法: 使用v2 API:
$ cat getTags.sh
#!/bin/bash
repo_url=https://registry.hub.docker.com/v2/repositories/
image_name=$1
url=${repo_url}/${image_name}/tags?page_size=1024
echo $url;
curl -L -s $url;
$ bash getTags.sh biocontainers/vcftools
注意:基础镜像要写前缀 bash getTags.sh library/ubuntu
输出结果复制
==> 打开chrome浏览器,按f12打开控制台console,
> t1= 粘贴刚才的输出。等号右侧最外层是{},不用加引号。
> for(i=0; i<t1.count; i++){ console.log(t1.results[i].name) }
v0.1.16-1-deb_cv1
v0.1.14_cv2
v0.1.15_cv2
v0.1.14_cv1
v0.1.15_cv1
0.1.14
0.1.15
然后就可以下载最新稳定版
$ docker pull biocontainers/vcftools:0.1.15
$ docker run --rm -it biocontainers/vcftools:0.1.15 bash
biodocker@dc1fb0dfabaf:/data$ vcftools --version
VCFtools (0.1.15)
其实有更简单的v1 API,这个输出信息比较少,结果可以直接肉眼看。
$ curl -L -s https://registry.hub.docker.com/v1/repositories/biocontainers/vcftools/tags
[{"layer": "", "name": "0.1.14"}, {"layer": "", "name": "0.1.15"}, {"layer": "", "name": "v0.1.14_cv1"}, {"layer": "", "name": "v0.1.14_cv2"}, {"layer": "", "name": "v0.1.15_cv1"}, {"layer": "", "name": "v0.1.15_cv2"}, {"layer": "", "name": "v0.1.16-1-deb_cv1"}]
==> chrome F12 console:
t2=[...]
for(var i=0; i<t2.length; i++){console.log(t2[i].name)}
结果同上。
(4) 重命名一个容器
老容器没有删除,且他们的id相同
$ docker tag openjdk:9.0.1-11-slim dawneve/openjdk:slim #旧名字:新名字
(5) 查看已经下载的镜像
$ docker images #查看本地存在的镜像
$ docker image ls #新风格的命令: 子命令
REPOSITORY TAG IMAGE ID CREATED SIZE
dawneve/openjdk slim 5149033ba93d 3 years ago 374MB
openjdk 9.0.1-11-slim 5149033ba93d 3 years ago 374MB
(6) 移除本地镜像
$ docker rmi dawneve/openjdk:slim
(7) 清理所有未打过标签的本地镜像:
$ docker rmi $(docker images -q -f "dangling=true")
其中 -q 和 -f 是 quiet,–filter 的缩写, 完整的命令其实可以写着下面这样,是不是更容易理解一点?
$ docker rmi $(docker images --quiet --filter "dangling=true")
进入容器后,很多docker是非常轻量的,默认没有vi/vim,但也不必装,不建议直接在容器中更改配置文件等信息。可以把宿主机编辑好的配置文件挂载到容器内的配置文件上。
(1) 基础命令
$ docker run ubuntu /bin/echo 'hello world' #运行一条命令后直接退出
$ docker run --name myUbt -it ubuntu /bin/bash #进入docker容器
root@e780bf085516:/# exit
exit
-t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上,
-i 则让容器的标准输入保持打开。
--name 给容器自定义一个名字
$ docker run -d --name mynginx nginx #启动nginx镜像,没有会自动pull
-d, --detach Run container in background and print container ID 后台运行容器,并打印容器id
注: 容器是否会长久运行,是和docker run指定的命令有关,和 -d 参数无关。
$ docker run --rm --name myUbt2 -it ubuntu /bin/bash #运行完删除容器文件
--rm Automatically remove the container when it exits
(2) 端口映射 -p
按照当前政策规定,很多单位的80端口路由器是不转发的,所以想访问只能设置为其他值。
$ docker run -d -p 91:80 --name mynginx2 nginx # -p 指定端口映射,host的91端口指向docker的80端口
访问宿主机的IP:91即可看到 nginx的欢迎页: http://192.168.2.242:91/
(3) 文件映射 -v,文件挂载 --mount
-v hostPath/:dockerPath/
--mount type=bind,source=/home/wangjl/,target=/test/ #支持挂载文件
实例1: 启动一个docker,使宿主机某个文件夹可以web访问
$ docker exec -it mynginx2 bash
root@5911b4776952:/# nginx -version
nginx version: nginx/1.21.3 #版本号
root@5911b4776952:/# cat /etc/nginx/conf.d/default.conf #查询根目录地址
root /usr/share/nginx/html;
root@5911b4776952:/# ls /usr/share/nginx/html/
50x.html index.html
做文件映射
$ docker run --rm -d -p 92:80 -v /home/wangjl/:/usr/share/nginx/html/ nginx
访问本机IP:92,可以看到 http://192.168.2.242:92/outer.html
==> 缺点: 该docker内部没有vim/vi,配置文件无法修改。也外部提供一个?
$ cat nginx.config
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
# list files
autoindex on;
autoindex_exact_size on;
autoindex_localtime on;
}
}
$ docker run --rm -d -p 93:80 \
--mount type=bind,source=/home/wangjl/,target=/usr/share/nginx/html/ \
--mount type=bind,source=/home/wangjl/nginx.config,target=/etc/nginx/conf.d/default.conf \
nginx
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bc0a93c4df18 nginx "/docker-entrypoint.…" 6 seconds ago Up 3 seconds 0.0.0.0:93->80/tcp, :::93->80/tcp loving_mirzakhani
宿主机打开 http://192.168.2.242:93/ 能看到文件列表了。
该方法特别适合查看主机上画的图片,只需要设定启动docker时的source目录即可。
实例2: 使用docker 编译java源代码
我主机上没有安装java,但是想编译和运行java怎么办?
查看docker内的java的版本号
$ docker run --rm -v /home/wangjl/:/test/ openjdk:9.0.1-11-slim java --version
openjdk 9.0.1
OpenJDK Runtime Environment (build 9.0.1+11-Debian-1)
OpenJDK 64-Bit Server VM (build 9.0.1+11-Debian-1, mixed mode)
写java代码
$ pwd
/home/wangjl
$ cat Hello.java
public class Hello {
public static void main(String args[]) {
System.out.println("Hello world, from Java!");
}
}
在容器中编译和运行
$ docker run --rm -v /home/wangjl/:/test/ openjdk:9.0.1-11-slim bash -c 'cd /test/ && javac Hello.java'
$ docker run --rm -v /home/wangjl/:/test/ openjdk:9.0.1-11-slim bash -c 'cd /test/ && java Hello'
Hello world, from Java!
文件挂载(推荐) --mount,并运行多个shell命令
该方法是挂载,可以挂载目录和文件。
$ docker run --rm --mount type=bind,source=/home/wangjl/,target=/test/ openjdk:9.0.1-11-slim bash -c 'cd /test/ && java Hello'
Hello world, from Java!
(4) 设置工作目录 --workdir=/home/tom/
i)使用 -v 挂载,在~/test/中编译java文件 ~/Hello.java
$ mkdir test
$ docker run --rm \
--volume /home/wangjl/test:/home/tom/:rw \
--volume /home/wangjl/Hello.java:/home/tom/Hello.java:ro \
--workdir=/home/tom/ \
openjdk:9.0.1-11-slim \
javac Hello.java
$ ls -lth test
total 4.0K
-rw-r--r-- 1 root root 427 Sep 15 10:13 Hello.class
-rwxr-xr-x 1 root root 0 Sep 15 10:13 Hello.java
ii) 使用 --mount 挂载,用docker运行java程序 ~/test/Hello.class
$ docker run --rm \
--mount type=bind,source=/home/wangjl/test,target=/test/,readonly \
--workdir=/test/ \
openjdk:9.0.1-11-slim java Hello
输出: Hello world, from Java!
# 实例3: 运行一个 mysql 实例,做文件映射和端口映射
$ docker pull hub.c.163.com/library/mysql:8.0 #拉镜像
帮助页面: https://c.163.com/hub#/m/repository/?repoId=2955 需要先登录网易账号。
Dockerfile: https://github.com/docker-library/mysql/blob/dc60c4b80f3eb5b7ef8b9ae09f16f6fab7a2fbf5/8.0/Dockerfile
$ docker tag hub.c.163.com/library/mysql:8.0 mysql:8.0 #改名字
运行该镜像:使用 -e 设置参数。
$ docker run -p 8088:3306 -d -it -e MYSQL_ROOT_PASSWORD=123456 -v /home/wangjl/dbFile:/var/lib/mysql mysql:8.0
0c9e8a4e20
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0c9e8a4e206f mysql:8.0 "docker-entrypoint.s…" 10 seconds ago Up 8 seconds 0.0.0.0:8088->3306/tcp, :::8088->3306/tcp serene_carson
$ ls -lth dbFile/
已经有很多东西了,这些文件都在宿主机上,不会随着docker的删除而消失。
可以尝试从网络中其他主机,连接宿主机的8088端口
(2) 使用 ubuntu 20.04
$ mysql -V
mysql Ver 8.0.26-0ubuntu0.20.04.3 for Linux on x86_64 ((Ubuntu))
$ mysql -h 192.168.2.242 -P 8088 -uroot -p
Enter password:
ERROR 2026 (HY000): SSL connection error: error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol
$ telnet 192.168.2.242 8088 #可以访问。
搜了一下
i) 方法1
https://www.cnblogs.com/milton/p/12831113.html
修改 /etc/ssl/openssl.cnf
找到 oid_section = new_oids 这行,并在其下 补充以下内容
openssl_conf = default_conf
[default_conf]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
MinProtocol = TLSv1
MaxProtocol = None
CipherString = DEFAULT:@SECLEVEL=1
重启ssh
$ sudo service ssh restart
还是不行。
ii) 或者加上参数 --ssl-mode=disabled
https://stackoverflow.com/questions/61649764/mysql-error-2026-ssl-connection-error-ubuntu-20-04
$ mysql -h 192.168.2.242 -P 8088 --ssl-mode=disabled -uroot -p
mysql> use mysql
mysql> select Host, User from user;
+-----------+-----------+
| Host | User |
+-----------+-----------+
| % | root |
| localhost | mysql.sys |
| localhost | root |
+-----------+-----------+
3 rows in set (0.00 sec)
(3) 从windows登录呢?
G:\xampp\mysql\bin>mysql -V
mysql Ver 15.1 Distrib 10.1.30-MariaDB, for Win32 (AMD64)
G:\xampp\mysql\bin>
G:\xampp\mysql\bin>mysql -h 192.168.2.242 -P 8088 -uroot -p
Enter password: ******
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.1-dmr MySQL Community Server (GPL)
MySQL [(none)]>
能找到 Rstudio 和 Seurat 的官方镜像。如何一起使用呢?
本测试使用的宿主机是一个硬件厉害的 centOS7 主机。
1.参考 Seurat 官网 install 目录下最后几行。
https://satijalab.org/seurat/articles/install.html
https://hub.docker.com/r/satijalab/seurat
We provide docker images for Seurat via dockerhub.
rstudio 专栏: https://environments.rstudio.com/docker
(1)To pull the latest image from the command line:
docker pull satijalab/seurat:latest
查看可用标签
https://hub.docker.com/r/satijalab/seurat
最新式 4.0.3
$ docker pull satijalab/seurat:4.0.3
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
satijalab/seurat 4.0.3 8852687a5c21 3 months ago 3.61GB
2) 如果拉取失败,只能让其他人拉取后打包发过来,再导入。
$ docker save -o seurat_4.0.3.tar satijalab/seurat:4.0.3
另一台导入主机
$ docker load < seurat_4.0.3.tar
(2)To use as a base image in a new Dockerfile:
FROM satijalab/seurat:latest
2. 运行
(1) 运行
$ docker run -d -p 5000:8787 satijalab/seurat:4.0.0 bash #这个是测试语句,无法实际使用。
要保证端口没被占用: -p 20180:80
保证文件夹挂载合理: /home/wangjl/data/dockerHome/
$ docker run -it -d \
--mount type=bind,source=/home/wangjl/data/dockerHome/,target=/work/ \
--workdir=/work/ \
-p 20180:80 \
satijalab/seurat:4.0.3 bash
为了防止停止时数据被删除,最好不适用--rm参数。
就是个黑窗口。$ R 打开R。
只能在黑窗口下使用,不知道怎么用Rstudio。
加 GUI 有2个思路
- 在这个 seurat 镜像中安装一个 rstudio。尝试失败。
- 在 rstudio 镜像中安装 seurat 包。测试成功。
(2)貌似没有 Rstudio,安装进去?
$ docker exec -it 071a bash
# apt-get update
# apt-get install gdebi-core
# wget https://download2.rstudio.org/server/bionic/amd64/rstudio-server-1.4.1717-amd64.deb
# gdebi rstudio-server-1.4.1717-amd64.deb
## 检查效果
# service rstudio-server restart
没有效果,搞不定。
可能是没有export 端口?
2)不过里面的包可以搞出来
容器内部
# ls /usr/local/lib/R/site-library/ |wc
219 219 1850
容器外
$ mkdir /data/rawdata/R4.1_pkgs
$ docker cp 36db:/usr/local/lib/R/site-library/ /data/rawdata/R4.1_pkgs/
这些包大概有1G
$ du -sh /data/rawdata/R4.1_pkgs/site-library/
1.1G /data/rawdata/R4.1_pkgs/site-library/
复制完包,这个容器就可以关闭/删除了。
$ docker stop 071a
3. 尝试从头建立镜像
(1) 文件准备
- 拉基础镜像 satijalab/seurat:4.0.3
- 准备配置文件
$ cat Dockerfile
FROM satijalab/seurat:4.0.3
RUN apt-get update && apt-get install gdebi-core -y
# ADD rstudio-server-1.4.1717-amd64.deb /home/
# RUN cd /home && gdebi rstudio-server-1.4.1717-amd64.deb && rm rstudio-server-1.4.1717-amd64.deb
EXPOSE 8787
CMD ["bash"]
(2) 开始构建
由于 gdebi 命令后需要输入 y,不知道怎么实现,只好采用注释掉,进容器安装后,采用 commit 提交修改。
$ docker build -t r1 ./
安装rstudio
$ docker run --rm -it -v /home/wangjl/data/dockerHome:/home/work --workdir=/home/work/ r1 bash
root@906918b93347:/home/work# gdebi rstudio-server-1.4.1717-amd64.deb
y
新建用户
# usr=rstudio
# useradd -s /bin/bash -d /home/${usr} -m ${usr}
# passwd rstudio #密码是123456
加入sudo
# echo "rstudio ALL=(ALL:ALL) ALL" >> /etc/sudoers
提交修改
$ docker ps # 查看容器id
把该容器提交为新镜像
$ docker commit -m 'Seurat4.0.3+Rstudio' 002 r2
r2 latest 0f9887056dfc 4 seconds ago 4.53GB
加上可见意义的标签
$ docker tag r2 dawneve/seurat:4.0.3a
dawneve/seurat 4.0.3a 0f9887056dfc 7 minutes ago 4.53GB
(3) 启动,加上文件映射
$ docker run --rm -it -d -p 20180:8787 \
--mount type=bind,source=/home/wangjl/data/dockerHome/,target=/home/rstudio/data/ \
--workdir=/home/rstudio/ \
dawneve/seurat:4.0.3a
进入容器内部
$ docker exec -it 208 bash
重启rstudio
# service rstudio-server restart
# exit
exit
浏览器登陆
http://172.18.5.193:20180/
用户 rstudio
密码 123456
注: 该用户有sudo权限
注意:
- 宿主机文件夹 /home/wangjl/data/dockerHome/ 是和容器共享数据的,要设置 other 可写。
- 容器内仅 /home/rstudio/data/ 数据会保留,其他数据都会随着容器的停止而被删除。
4. 换个思路,从Rstudio 基础镜像,安装 Seurat包
https://hub.docker.com/r/rocker/rstudio/tags?page=1&ordering=last_updated
https://github.com/rocker-org/rocker-versioned2/issues
(1) 最新版是 4.1.1
$ docker pull rocker/rstudio:4.1.1
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
rocker/rstudio 4.1.1 1878e29db52f 13 days ago 1.93GB
(2) 改造
文件映射,直接说使用刚才Seurat镜像的R包。
$ docker run --rm -it -p 20181:8787 \
--mount type=bind,source=/data/rawdata/R4.1_pkgs/site-library/,target=/usr/local/lib/R/site-library/ \
--mount type=bind,source=/home/wangjl/data/dockerHome/,target=/home/rstudio/data/ \
--workdir=/home/rstudio/ \
-e PASSWORD=123 rocker/rstudio:4.1.1
还需要进入容器,安装几个包。
$ docker exec -it xxx bash
# apt update
# apt install libxml2 -y
# apt install libglpk-dev -y #比较大
## 可以载入 Seurat 了。
# apt install libxt-dev -y #解决一个warning
把该容器提交为新镜像
$ docker commit -m 'Rstudio with Seurat4.0.3' 21d dawneve/seurat:4.0.3b
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dawneve/seurat 4.0.3b 7b5fc23f2fd7 2 hours ago 2.1GB
这个小,是因为R包在宿主机上有单独的文件夹,不统计大小。
(4) 使用该新镜像,启动容器
$ docker run --rm -it -d -p 20180:8787 \
--mount type=bind,source=/data/rawdata/R4.1_pkgs/site-library/,target=/usr/local/lib/R/site-library/ \
--mount type=bind,source=/home/wangjl/data/dockerHome/,target=/home/rstudio/data/ \
--workdir=/home/rstudio/ \
-e PASSWORD=yourpasswordhere dawneve/seurat:4.0.3b
注意2点:
- 不能覆盖掉 /home/rstudio/ 文件夹,因为很多缓存文件在里面。
- 要在容器外,对可写文件夹设置可写操作 $ chmod 777 dockerHome/
- 容器内,除了 /home/rstudio/data/ 能保留,其他都会随着 docker 的停止而销毁!
打开浏览器 http://172.18.5.193:20180/
用户名: rstudio
密码: yourpasswordhere
-e DISABLE_AUTH=true \ 加上这一句就不用输入密码了,不过不安全。
(1) 查看容器状态
$ docker ps #查看正在运行的容器
$ docker ps -a #查看所有容器,再运行的和已经停止的
查看容器资源使用情况
$ docker stats 5911b
(2)停止、重新运行、删除一个容器
$ docker stop bfd0 #停止一个容器,根据容器 id
$ docker start bfd0 #开始一个停止的容器
$ docker rm bfd0 #删除一个容器。默认并不会删除运行中的容器,需要先stop
重命名容器
$ docker rename CONTAINER NEW_NAME
(3) 有关容器和镜像的底层信息
i) 镜像
$ docker inspect nginx:latest
可以查看:
容器实例的IP地址端口绑定列表
特定端口映射的搜索
收集配置的详细信息
ii) 查看容器的ip
$ docker inspect 5911b
...
"IPAddress": "172.17.0.3",
...
此时通过curl命令可以访问到,而浏览器则访问不到
$ curl 172.17.0.3 #内容略。
$ ping 172.17.0.3 #ttl=64 time=0.070 ms
(4) 进入容器内部
$ docker container exec -it container_id /bin/bash 进入到容器
$ docker exec -it 2ad bash
root@2ad472e991ba:/# exit #退出(docker容器中的命令,键入此命令,退回宿主机命令行)
(5) exec 向正在运行的容器下发命令
Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Options:
-d, --detach 在后台运行命令
-e, --env list 设置环境变量
-i, --interactive 以交互模式运行
-t, --tty 分配一个伪终端
-u, --user string 执行命令的用户
-w, --workdir string 工作目录
(6) 显示容器日志
Usage: docker logs [OPTIONS] CONTAINER
Options:
--details 显示详细日志
-f, --follow 跟随日志输出
--tail string 显示行数
-t, --timestamps 显示时间戳
$ docker logs 5911b
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
...
192.168.2.199 - - [15/Sep/2021:01:50:06 +0000] "GET /outer.html HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36" "-"
1.用途: 不同机器共享 docker 镜像。 (1)镜像的迁移,一个方法是传到仓库(公共或本地),另一个是使用文件。 使用Docker save和Docker load命令来存储和载入镜像。 命令: 对于容器,可以使用import和export 进行导入导出操作。 对于已有镜像,可以使用 docker命令行的 save 和 load 命令来创建压缩包tarball。 (2) 压缩的优势 压缩后体积大幅减少。 -rw-rw-r-- 1 wangjl wangjl 68M Apr 17 10:47 postgres_10.image.tar.gz -rw------- 1 wangjl wangjl 197M Apr 17 10:02 postgres_10.image.tar -rw-rw-r-- 1 wangjl wangjl 42M Apr 17 10:49 nginx_1.15.10.image.tar.gz -rw------- 1 wangjl wangjl 108M Apr 17 10:01 nginx_1.15.10.image.tar 2. 推荐导出压缩过的镜像 .tar.gz,节省磁盘空间 (1) 导出镜像并压缩: docker save myimage:tag | gzip > myimage_tag.image.tar.gz (2) 两个机器之间通过 scp 传输镜像文件。 $ scp from/path to/path/ (3) 解压并导入镜像: gunzip -c myimage_tag.image.tar.gz | docker load 推荐命名后缀 myimage_tag.image.tar.gz 推荐命名间隔 org__myimage_tag.image.tar.gz 实例:镜像的导入和导出 $ docker save bdgenomics/rhapsody:1.9.1 | gzip > bdgenomics__rhapsody_1.9.1.image.tar.gz $ gunzip -c bdgenomics__rhapsody_1.9.1.image.tar.gz | docker load之前的版本,没压缩,一般不用:
(1) 通过 tar 包导出、导入
打包镜像为tar包:
Usage: docker save [OPTIONS] IMAGE [IMAGE...]
Save one or more images to a tar archive (streamed to STDOUT by default)
$ docker save -o ubuntu_14.04.tar ubuntu:14.04
$ docker save -o jdk_9.0.1.tar openjdk:9.0.1-11-slim
使用 scp 命令跨主机传输
$ scp wangjl@y.biomooc.com:/home/wangjl/data/test/testCWL/jdk_9.0.1.tar .
新主机从tar包载入镜像:
$ docker load < jdk_9.0.1.tar
## 或者使用
$ cat jdk_9.0.1.tar| docker import - test/java:v9.0 #从tar包导入镜像,支持重命名镜像
## 其他形式
docker import "jdk_9.0.1.tar" test/java:v9.0
docker import jdk_9.0.1.tar test/java:v9.0 #推荐
(2) 还可以gz压缩
宿主机
$ docker save myRstudioIMG | gzip -c > myRstudioIMG.tar.gz
myRstudioIMG.tar.gz 传输到新机器上,再在新机器上导入gz包
$ gunzip -c myRstudioIMG.tar.gz | docker load
(3) 推送镜像到仓库 docker hub
之前我们一直从docker hub下载镜像,如果有本地制作好的docker,也可以上传。
前提是要注册一个docker账号: https://www.docker.com/
$ docker login -u 用户名
输入密码
登录后就可以推送了,只能推送到自己的仓库:https://hub.docker.com/u/dawneve
$ docker push dawneve/mysql
The push refers to a repository [docker.io/dawneve/mysql]
(4) export 将容器文件系统导出为一个tar包
Usage: docker export [OPTIONS] CONTAINER
Export a container's filesystem as a tar archive
Options:
-o, --output string tar包名称
(5) import 从压缩文件导入文件系统的镜像
Usage: docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
Import the contents from a tarball to create a filesystem image
i) 从容器内复制文件到宿主机指定的路径上
$ docker cp container:path hostpath
给nginx容器内放网页文件
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5911b4776952 nginx "/docker-entrypoint.…" 20 minutes ago Up 20 minutes 0.0.0.0:91->80/tcp, :::91->80/tcp mynginx2
$ docker exec -it 591 bash
root@5911b4776952:/# cat /etc/nginx/conf.d/default.conf | grep root
root /usr/share/nginx/html;
root@5911b4776952:/# exit
exit
$ echo "this is out.html" > outer.html
$ docker cp outer.html 5911:/usr/share/nginx/html/
http://192.168.2.242:91/outer.html 能看到内容:this is out.html
ii) 从容器中复制文件到外面:
$ docker cp 5911:/usr/share/nginx/html/50x.html .
$ wc 50x.html
19 68 497 50x.html
制作docker镜像主要包括 docker commit 方法和 Dockerfile 两种方法。对于运行的容器,如果有文件有变动,则可以使用commit命令提交为新的镜像。 推荐用Dockerfile文件建立镜像,因为该方法更可重复。下一章讲解 Dockerfile 法。
这里主要介绍前者。
commit制作镜像: 基于容器来制作image docker build: dockerfile 制作镜像 tar包制作镜像: import 基于容器来制作image 1. 在已有的docker镜像上提交修改。 $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5911b4776952 nginx "/docker-entrypoint.…" 13 hours ago Up 13 hours 0.0.0.0:91->80/tcp, :::91->80/tcp mynginx2 如果一个容器,我们复制进去一个文件,该变动可以提交为一个新镜像。 $ docker cp outer.html 5911:/usr/share/nginx/html/ 示例命令:docker commit -m '注释' 容器id 自定义镜像名 $ docker commit -m 'a new nginx container with outer.html' 5911 dawneve/static_web:addOuterFile sha256:8899f25a8afd1992e4fbb29c368886c45e9ca5d955a07dab8c19811233315722 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE dawneve/static_web addOuterFile 8899f25a8afd 18 seconds ago 133MB nginx latest ad4c705f24d3 5 days ago 133MB 该镜像运行,可以打包成tar文件,可以推送到远端docker hub。
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。每一行就是声明镜像的每层内容。
通过docker history nginx 可以看到一层层的内容。
编写的注意事项: #——表示注释 第一个非注释行一定要是FROM指令 编写dockerfile必须在一个目录下进行,这个目录就是dockerfile的工作目录 Dockerfile的文件名的首字母必须是大写:Dockerfile 制作镜像所要使用的文件必须放在工作目录之下,或者工作目录的子目录下面,不能放到其他目录之中。 基于dockerfile制作镜像本质上还是基于现有镜像去制作镜像。 可以通过隐藏文件.dockerignore来指定不要放到镜像中的文件,一行是一个文件。
$ docker build [OPTIONS] PATH | URL | - --rm Remove intermediate containers after a successful build (default true) --rm=true 表示构建成功后,移除所有中间容器 --no-cache Do not use cache when building the image –no-cache=false表示在构建过程中不使用缓存 $ vim Dockerfile FROM ubuntu:20.04 RUN apt-get update ADD run.sh / VOLUME /data CMD ["./run.sh"] # FROM 命令是 Dockerfile 中唯一不可缺少的命令,它为最终构建出的镜像设定了一个基础镜像(base image)。 准备脚本 $ vim run.sh echo "run now..." 开始构建 $ docker build -t="my_new_image" ./ Sending build context to Docker daemon 5.632kB Step 1/5 : FROM ubuntu:20.04 # 第一步 下载ubuntu:20.04 20.04: Pulling from library/ubuntu Digest: sha256:9d6a8699fb5c9c39cf08a0871bd6219f0400981c570894cd8cbea30d3424a31f Status: Downloaded newer image for ubuntu:20.04 ---> fb52e22af1b0 Step 2/5 : RUN apt-get update #第二步 更新系统源 ---> Running in 4989d5ad814f Get:1 http://archive.ubuntu.com/ubuntu focal InRelease [265 kB] ... Get:18 http://archive.ubuntu.com/ubuntu focal-backports/main amd64 Packages [2668 B] Fetched 19.1 MB in 26s (742 kB/s) Reading package lists... Removing intermediate container 4989d5ad814f ---> a814eb9f4bf0 Step 3/5 : ADD run.sh / # 第三步 复制宿主机文件到镜像内 / 下。 ---> fea27e209490 Step 4/5 : VOLUME /data # 第四步 添加目录 ---> Running in 9ca454a8e5eb Removing intermediate container 9ca454a8e5eb ---> 02feb24f1a08 Step 5/5 : CMD ["./run.sh"] # 第五步 执行该脚本 ---> Running in 082ca5572878 Removing intermediate container 082ca5572878 ---> af246f32db94 Successfully built af246f32db94 Successfully tagged my_new_image:latest #最后添加标签 检查产生的镜像 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE my_new_image latest af246f32db94 48 seconds ago 103MB $ docker run --rm -it my_new_image bash root@80f829d85f8a:/# bash run.sh run now.. root@80f829d85f8a:/# exit exit 看第二列的时间,Docker Daemon 新创建了 4 层镜像,除了 FROM 命令,其余的 RUN、ADD、VOLUME 以及 CMD 命令都会创建一层新的镜像。 $ docker history my_new_image IMAGE CREATED CREATED BY SIZE COMMENT af246f32db94 8 minutes ago /bin/sh -c #(nop) CMD ["./run.sh"] 0B 02feb24f1a08 8 minutes ago /bin/sh -c #(nop) VOLUME [/data] 0B fea27e209490 8 minutes ago /bin/sh -c #(nop) ADD file:08a4b2c0a3a1ce10d… 18B a814eb9f4bf0 8 minutes ago /bin/sh -c apt-get update 30.4MB fb52e22af1b0 2 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B <missing> 2 weeks ago /bin/sh -c #(nop) ADD file:d2abf27fe2e8b0b5f… 72.8MB
书写 Dockerfile 时,应该将更多静态的安装、配置命令尽可能地放在 Dockerfile 的较前位置。
实例2: 构建一个带 gcc 编译器的docker,顺便带上 gdb最佳实践 - Require 明确:需要什么镜像 - 步骤精简:变化较少的 Step 优先 - 版本明确:镜像命名明确 - 说明文档:整个镜像打包步骤可以重现
$ cat Dockerfile
FROM ubuntu:20.04
WORKDIR /app
RUN apt-get update && apt-get install gcc gdb -y
注意:RUN 命令不更新不让安装包
$ docker build -t gcc ./
...
Successfully built ca894de5b7c5
Successfully tagged gcc:latest
查看生成的镜像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
gcc latest ca894de5b7c5 28 minutes ago 399MB
x x 88d6f843beb8 3 minutes ago 233MB #没有 gdb时
查看版本
$ docker run --rm -it gcc:latest gdb --version
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
$ docker run --rm -it -v /home/wangjl/test:/app --workdir=/app gcc:latest gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
编写一个c程序
$ cat hello.c
#include <stdio.h>
int main(){
printf("hello, world! from c\n");
}
编译: docker内编译
$ docker run --rm -it -v /home/wangjl/test:/app --workdir=/app gcc:latest gcc hello.c
运行:直接在宿主机运行二进制文件
$ ./a.out
hello, world! from c
上文用到的 nginx 镜像的构建文件: https://github.com/nginxinc/docker-nginx/blob/d496baf859613adfe391ca8e7615cc7ec7966621/mainline/debian/Dockerfile 上文用到的 mysql 镜像的构建文件: https://github.com/docker-library/mysql/blob/dc60c4b80f3eb5b7ef8b9ae09f16f6fab7a2fbf5/8.0/Dockerfile Best practices for writing Dockerfiles https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ Dockerfile reference:https://docs.docker.com/engine/reference/builder/
常用的是11个命令。
1.ARG 设置参数,该参数值可以从 --build-arg <varname>=<value> 接收值 在FROM之前的ARG参数只在FROM语句中生效,若在FROM之后想要继续使用ARG,需要再次设置 Usage: ARG <name>[=<default value>] 例:ARG version="1.0.0"
FROM 指定基础镜像,FROM必须为Dockerfile非注释行的第一行。 Usage: FROM <image> FROM <image>:<tag> FROM <image>@<digest> 例:FROM ubuntu:14.04
LABEL 设置镜像标签 Usage: LABEL <key>=<value> <key>=<value> <key>=<value> ... 例:LABEL maintainer="demo@demo.com" 例:LABEL version="1.0" description="这是一个web应用"
ENV 设置环境变量 建议:不论用哪种书写方式,在实际使用中,一行都只写一个环境变量,方便阅读。 特别地:在使用docker run命令添加参数 --env 时,若有相同的环境变量,以run命令为准。 Usage: ENV <key> <value> ENV <key>=<value> ... ENV <key> <value>此方法一次只能设置一个 ENV <key>=<value> ... 该方法一次可以设置多个环境变量 例:ENV JAVA_HOME=/home/jdk-8
ADD
将主机构建环境(上下文)目录中的文件和目录、或URL标记的文件 拷贝到镜像中。
Usage:
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
例:ADD ${WORKSPACE}/target /usr/local/tomcat/webapps/ROOT
ADD t2.txt.gz /app/ #txt.gz 不会被解压
ADD all.tar /app/ #tar 会被解压
ADD txt.tar.gz /app/ #.tar.gz 会被解压
ADD http://www.baidu.com/index.html B1.html #支持url下载
ADD data1 data1 #支持目录拷贝
COPY 添加文件,将宿主机的文件添加到镜像中。 Usage: COPY [--chown=<user>:<group>] <src>... <dest> COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
USER 指定运行容器的用户 Usage: USER <user>[:<group>] USER <UID>[:<GID>] 例:USER root
WORKDIR 工作目录,进入容器后,以 WORKDIR 为当前路径 设置工作目录后 ,RUN、CMD、COPY、ADD 的工作目录都会同步变更 Usage: WORKDIR /workdir 例:WORKDIR /home WORKDIR /app/test
EXPOSE 说明容器暴露的端口,默认协议为 tcp ,若是 udp 协议,则需要在后面添加 udp ,如 80/udp Usage: EXPOSE <port> [<port>/<protocol>...] 例:EXPOSE 8080,表明容器在运行时提供8080端口,在启动该容器时需端口映射。
VOLUME 设置挂载点,将容器内的路径挂载到宿主机,该挂载方式是将容器内的路径挂载到docker数据路径下 Usage: VOLUME <url> 例:VOLUME /var/log # 指定容器中需要被挂载的目录,会把这个目录映射到宿主机的一个随机目录上,实现数据的持久化和同步。 VOLUME ["/var/log", "/var/test" …..] 指定容器中多个需要被挂载的目录,会把这些目录映射到宿主机的多个随机目录上,实现数据的持久化和同步 VOLUME /var/data var/log 指定容器中的 var/log 目录挂载到宿主机上的 /var/data 目录,这种形式可以手动指定宿主机上的目录
RUN 执行命令并创建新的镜像层,通常用于更新或安装软件。 Usage: RUN <command> RUN ["executable", "param1", "param2"] 例:RUN yum -y install git
CMD 设置容器启动后默认执行的命令,CMD命令会被docker run的参数覆盖。 Usage: CMD <command> CMD ["executable","param1","param2"] 例:CMD systemclt start docker.service //启动容器时启动docker服务
ENTRYPOINT 和CMD一样,设置容器启动后默认执行的命令,但是该命令不会被docker run覆盖,会始终执行,CMD会被docker run传入的命令覆盖。 Usage: ENTRYPOINT <command> ENTRYPOINT ["executable", "param1", "param2"] 例:ENTRYPOINT /usr/local/apache-tomcat-8.5.33/bin/startup.sh
Demo
FROM tomcat:9.0
LABEL maintainer="demo@demo.com"
ADD ${WORKSPACE}/target/cip-file-1.0.0-SNAPSHOT /opt/apache-tomcat- 9.0.12/webapps/file
ENV LC_ALL en_US.UTF-8 EXPOSE 8080
ENTRYPOINT /opt/apache-tomcat-9.0.12/bin/startup.sh && tail -f /opt/apache- tomcat-9.0.12/logs/catalina.out
Singularity是劳伦斯伯克利国家实验室专门为大规模、跨节点HPC和DL工作负载而开发的容器化技术。具备轻量级、快速部署、方便迁移等诸多优势,且支持从Docker镜像格式转换为Singularity镜像格式。
https://sylabs.io/docs/ https://sylabs.io/guides/3.8/user-guide/ http://hpc.pku.edu.cn/_book/guide/soft_env/Singularity.html https://github.com/hpcng/singularity https://singularity.hpcng.org/
使用虚拟机中的 ubuntu20.04 再次安装
$ wget https://github.com/sylabs/singularity/releases/download/v3.8.3/singularity-ce-3.8.3.tar.gz
-rw-rw-r-- 1 wangjl wangjl 8.1M Sep 2 01:25 singularity-ce-3.8.3.tar.gz
$ tar zxvf singularity-ce-3.8.3.tar.gz
$ cd singularity-ce-3.8.3/
$ vim README.md
安装请看 INSTALL.md
$ vim INSTALL.md
(1)安装开发工具和包
$ sudo apt-get update
$ sudo apt-get install -y build-essential \
libseccomp-dev pkg-config squashfs-tools cryptsetup
The following packages have unmet dependencies:
build-essential : Depends: libc6-dev but it is not going to be installed or
libc-dev
Depends: g++ (>= 4:7.2) but it is not going to be installed
Depends: dpkg-dev (>= 1.17.11) but it is not going to be installed
libseccomp-dev : Depends: libseccomp2 (= 2.5.1-1ubuntu1~18.04.1) but 2.5.1-1ubuntu1~20.04.1 is to be installed
E: Unable to correct problems, you have held broken packages. ##这是个啥?
出错:
虚拟机恢复Ubuntu20.04到出厂设置,使用原版源安装一切正常。
莫名其妙... 可能是源在同步中?之前的源是tsinghua,现在是默认cn.ubuntu源。
(2) 安装Go语言 install and configure golang: https://golang.org/doc/install
$ sudo apt install golang-go
$ which go
/usr/bin/go
$ go version
go version go1.13.8 linux/amd64
(3) 回去安装
$ cd singularity-ce-3.8.3/
$ ./mconfig && \
cd ./builddir && \
make ##特别耗时,30min?
$ sudo make install #也耗时很久
(4) 检查版本号
$ singularity --version
singularity-ce version 3.8.3
表示安装成功。
(5) 查看帮助
$ singularity
$ singularity --help
生信常用的镜像 https://singularityhub.github.io/singularity-hpc/ https://github.com/pscedu/singularity-bowtie2 https://github.com/pscedu/singularity-samtools https://singularityhub.github.io/singularity-hpc/r/biocontainers-samtools/
1. 命令行搜索 $ singularity search samtools Found 15 container images for amd64 matching "samtools": library://alesr13/default/samtools_bwa_picard:v0.1 Signed by: 6e23de6eac622dd1d96f304af7b50e57f44404e7 library://btmiller/default/testimg-bowtie2-samtools:latest library://daanjg98/rnaseq/samtools:1.11 2. 从搜索结果中选一个靠谱的,建立sif镜像 $ TMPDIR=$PWD singularity build samtools.sif library://daanjg98/rnaseq/samtools:1.11 INFO: Build complete: samtools.sif -rwxr-xr-x 1 wangjl wangjl 170M Sep 16 17:43 samtools.sif 查看版本号: $ singularity exec samtools.sif samtools --version samtools 1.11 Using htslib 1.11 Copyright (C) 2020 Genome Research Ltd. 据说还能这样执行: $ ./samtools.sif samtools --version samtools 1.11 Using htslib 1.11 Copyright (C) 2020 Genome Research Ltd. 3. 拷贝过来一个 bam 文件 不认识其他目录,只认识 $HOME 目录。 $ ls /data lost+found wangjl $ singularity exec samtools.sif bash bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8) Singularity> cd /data bash: cd: /data: No such file or directory Singularity> ls /|grep data Singularity> cd ~/test Singularity> samtools view cgm-90.sort.bam | wc 57814 994108 22848219 Singularity> exit exit 4. 查看bam,并把 bam 转 sam 容器启动时所在的工作目录 $ singularity exec samtools.sif pwd /home/wangjl (1) 查看bam文件 完整运行模式: 要使用完整路径: $ singularity exec samtools.sif samtools view ~/test/cgm-90.sort.bam | wc -l #57814 简化运行,就像一个local命令一样 $ ./samtools.sif samtools view ~/test/cgm-90.sort.bam | wc -l #57814 $ ./samtools.sif samtools view ~/test/cgm-90.sort.bam | head -n 2 A00582:646:H7CJTDSX2:4:1603:3884:9627 147 chr1 10000 0 53S91M = 10004 -87 AGATCTAGACTATCCTCTTCGTCGGCAGAGTAAGATGTTTATAAGAGACAGACATAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCC F:FF,FF,:,F,F::FFFFFFF,,:,,:,:F,F:FF:F,F:F,,F,F,,F:,F,FF:FF:FF::F,:F::FFFFFF,FFFFF,FF:F,F::FFF,F:FFF:::F:FFFF:::F:::FFFFFFF:::FFF::FFFFFFFFFFFFF NM:i:0 MD:Z:91 MC:Z:93M AS:i:91 XS:i:90 RG:Z:cgm-90 A00582:646:H7CJTDSX2:4:1603:3884:9627 99 chr1 10004 0 93M = 10000 87 CCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCC FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:FF:FFFFF:FFFFFFFFFFF,FFFFF:FFFFF,F,,F, NM:i:0 MD:Z:93 MC:Z:53S91M AS:i:93 XS:i:93 RG:Z:cgm-90 wangj (2) bam to sam $ singularity exec -B /home/wangjl/test:/home/wangjl samtools.sif samtools view -h cgm-90.sort.bam -o xx.sam $ ls -lth ~/test total 24M -rw-rw-r-- 1 wangjl wangjl 22M Sep 16 21:09 xx.sam -rw-rw-r-- 1 wangjl wangjl 2.1M Sep 16 19:51 cgm-90.sort.bam
$ docker pull ubuntu:20.04
1. 生成 sif 镜像
有多种方法:
(1)获取预编译镜像 (会在当前目录下下载 ubuntu_tag.sif 文件)
$ singularity pull docker://ubuntu:20.04 #虽然docker下过,还要下载
(2)从 Docker Hub build 镜像
$ singularity -d build ubuntu.sif docker://ubuntu:20.04 #很多屏的输出,没看出是否下载
(3)从本地缓存生成 镜像
$ singularity build ubuntu_20.04-v2.sif docker-daemon://ubuntu:20.04
(4)从镜像tar文件开始
$ docker save ubuntu:20.04 -o ubuntu20.04.tar
-rw------- 1 wangjl wangjl 72M Sep 16 15:15 ubuntu20.04.tar
$ singularity build ubuntu_20.04-v3.sif docker-archive://ubuntu20.04.tar
结果4个文件 大小一样,md5互不一样。
-rwxr-xr-x 1 wangjl wangjl 27M Sep 16 10:55 ubuntu.sif
-rwxrwxr-x 1 wangjl wangjl 27M Sep 16 10:53 ubuntu_20.04.sif
-rwxr-xr-x 1 wangjl wangjl 27M Sep 16 15:10 ubuntu_20.04-v2.sif
-rwxr-xr-x 1 wangjl wangjl 27M Sep 16 15:16 ubuntu_20.04-v3.sif
2. 运行
(1) 交互模式运行 singularity shell
shell Run a shell within a container
$ singularity shell ubuntu_20.04.sif
Singularity> pwd
/home/wangjl
Singularity> id
uid=1000(wangjl) gid=1000(wangjl) groups=1000(wangjl),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),120(lpadmin),132(lxd),133(sambashare),134(docker)
Singularity> vim ReadMe
bash: vim: command not found
Singularity> ping baidu.com
bash: ping: command not found
Singularity> exit
exit
怎么看着就是宿主机呢?目录、用户继承宿主机。
宿主机有命令ping、vim, 内部没有。
难道只是虚拟的命令环境,但是文件系统还是宿主机的?如果这样,就特别适合做 java/C的编译了!
(2) 执行一个命令并退出 singularity exec
exec Run a command within a container
$ singularity exec ubuntu.sif bash -c "pwd && id"
/usr/bin/bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
/home/wangjl
uid=1000(wangjl) gid=1000(wangjl) groups=1000(wangjl),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),120(lpadmin),132(lxd),133(sambashare),134(docker)
$
(3) 运行一个容器 singularity run,感觉和 shell 一样?
run Run the user-defined default command within a container
使用run只执行一句,效果类似 exec
$ singularity run ~/data/ubuntu_20.04.sif echo "hello"
hello
如果不接命令,则和 shell 子命令一样,进入交互状态。
$ singularity run ubuntu.sif
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
Singularity> pwd
/home/wangjl
Singularity> groups
wangjl adm cdrom sudo dip plugdev lpadmin lxd sambashare docker
Singularity> exit
exit
$
在内部写一个文件 01.txt
$ singularity run ubuntu.sif
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
Singularity> echo "line1">01.txt
Singularity> exit
exit
$ cat 01.txt
line1
$ ls -lth
total 184M
-rw-rw-r-- 1 wangjl wangjl 6 Sep 16 11:11 01.txt
(4) 后台运行容器实例,作为一个服务
instance Manage containers running as services
启动实例
$ singularity instance start ubuntu.sif test1
$ singularity instance start ubuntu.sif test2
查看实例:只有IP,没有端口列 (类似于docker ps)
$ singularity instance list
INSTANCE NAME PID IP IMAGE
test1 62541 /home/wangjl/ubuntu.sif
test2 62581 /home/wangjl/ubuntu.sif
操作实例
可以通过 shell, exec, run 命令来连到容器中运行命令
使用 shell 命令连入容器
$ singularity shell instance://test1
Singularity> cat 01.txt
line1
Singularity> exit
exit
使用 exec 执行命令
$ singularity exec instance://test2 cat 01.txt
line1
停止实例
$ singularity instance stop test1
$ singularity instance stop test2
关闭(并删除)容器,更像是 docker stop + docker rm,所以轻易不要stop,只用 exit 就行了。
(5) 绑定目录 -B
在 Singularity 中也可以在 shell, run, instance.start 等命令中通过 “-B” 选项来实现 Docker 中 “-v” 选项提供挂载卷的功能,比如:
$ singularity shell -B /apps:/apps ubuntu.sif
挂在多个用逗号隔开: -B /home/tom:/home/tom,/home/tom/dataset:/home/dataset \
$ singularity shell --help
Run a shell within a container
-B, --bind strings a user-bind path specification.
spec has the format src[:dest[:opts]], where src and dest are outside and inside paths. 路径内外的映射?
If dest is not given, it is set equal to src.
Mount options ('opts') may be specified as 'ro' (read-only) or 'rw' (read/write, which is the default). Multiple bind paths can be given by a comma separated list.
$ singularity shell -B /tmp:/apps ubuntu.sif
Singularity> ls -lth /apps #虚拟的目录
total 48K
drwx------ 2 wangjl wangjl 4.0K Sep 16 11:11 tracker-extract-files.1000
Singularity> exit
exit
$ ls -lth /tmp #宿主机的目录
total 48K
drwx------ 2 wangjl wangjl 4.0K Sep 16 11:11 tracker-extract-files.1000
(6) --fakeroot 啥意思?在容器内有root权限 //todo
The --fakeroot option is available with the following singularity commands:
shell
exec
run
instance start
build
$ singularity exec --fakeroot docker://ubuntu:20.04 ls -lth
$ singularity exec --fakeroot ~/data/ubuntu_20.04.sif ls -lth
INFO: Converting SIF file to temporary sandbox...
...
INFO: Cleaning up image...
https://uh.edu/rcdc/resources/software/Singularity.php
1. Get the docker image and convert it to singularity image,
$ singularity pull docker://dawneve/mysql #缺点:singularity 没法做端口映射,那就只能开一个
INFO: Converting OCI blobs to SIF format
INFO: Starting build...
Getting image source signatures
Copying blob d08a2c3112d4 done
...
Writing manifest to image destination
Storing signatures
2021/09/16 10:13:20 info unpack layer: sha256:d08a2c3112d431c43e02458a285501d289333380438e760962619c8672bcbe0b
...
INFO: Creating SIF file...
$ ls -lth
total 131M
-rwxrwxr-x 1 wangjl wangjl 131M Sep 16 10:17 mysql_latest.sif
2. To open an interactive shell inside the container,
$ singularity shell mysql_latest.sif
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
Singularity> mysql --version
mysql Ver 14.14 Distrib 5.7.18, for Linux (x86_64) using EditLine wrapper
Singularity> exit
exit
3. To directly execute a command inside your container environment,
## singularity exec shub://singularityhub/ubuntu cat /etc/os-release
$ pwd
/home/wangjl/data/dbFile
$ mkdir -p ${PWD}/mysql/var/lib/mysql ${PWD}/mysql/run/mysqld
$ singularity instance start --bind ${HOME} \
--bind ${PWD}/mysql/var/lib/mysql/:/var/lib/mysql \
--bind ${PWD}/mysql/run/mysqld:/run/mysqld \
mysql_latest.sif mysql
## INFO: instance started successfully
$ singularity instance list
INSTANCE NAME PID IP IMAGE
mysql 3115 /home/wangjl/data/dbFile/mysql_latest.sif
$ singularity run instance://mysql #报错
error: database is uninitialized and password option is not specified
You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD
这个报错怎么解决?
docker的-e参数,这里是什么?是 --env
$ singularity run --env MYSQL_ROOT_PASSWORD=123456 instance://mysql
4.连接该数据库,并新建库和表
$ ifconfig #查宿主机的ip
192.168.2.242
不支持端口映射,那就是 3306 端口本身了。
从能访问宿主机的地方登陆mysql。
$ mysql -h 192.168.2.242 -P 3306 -uroot -p
mysql> create database wang;
mysql> use wang;
Database changed
CREATE TABLE `think_weibo` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`uid` int(20) NOT NULL,
`content` text,
`add_time` varchar(30) DEFAULT NULL,
`cid` int(10) DEFAULT NULL,
`archive` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into think_weibo values(1,101,"ctx1", "20210901",1, 0),(2,202,"ctx2", "20210902",2, 1);
mysql> select * from think_weibo;
+----+-----+---------+----------+------+---------+
| id | uid | content | add_time | cid | archive |
+----+-----+---------+----------+------+---------+
| 1 | 101 | ctx1 | 20210901 | 1 | 0 |
| 2 | 202 | ctx2 | 20210902 | 2 | 1 |
+----+-----+---------+----------+------+---------+
2 rows in set (0.00 sec)
mysql> exit
Bye
5. 查看文件
$ ls -lth dbFile/mysql/var/lib/mysql/wang
total 112K
-rw-r----- 1 wangjl wangjl 96K Sep 16 16:32 think_weibo.ibd
-rw-r----- 1 wangjl wangjl 8.6K Sep 16 16:29 think_weibo.frm
-rw-r----- 1 wangjl wangjl 65 Sep 16 16:28 db.opt
6.退出该容器
$ singularity instance stop mysql
INFO: Stopping mysql instance of /home/wangjl/data/dbFile/mysql_latest.sif (PID=3115)
1. 如前教程,安装docker
$ docker pull openjdk:9.0.1-11-slim
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
openjdk 9.0.1-11-slim 5149033ba93d 3 years ago 374MB
$ pwd
/home/wangjl/test
$ cat Hello.java
public class Hello {
public static void main(String args[]) {
System.out.println("Hello world, from Java!");
}
}
$ docker run --rm -v /home/wangjl/test:/test/ openjdk:9.0.1-11-slim bash -c 'cd /test/ && javac Hello.java && java Hello'
Hello world, from Java!
2. 构建镜像文件
(1)从本地缓存的镜像构建 sif 文件
$ singularity build openjava9-v1.sif docker-daemon://openjdk:9.0.1-11-slim
注意:从原来的docker变成了docker-daemon;必须加tag标签;
如果撑爆 /tmp 临时文件夹,则把临时文件夹改在当前文件夹内:
$ TMPDIR=$PWD singularity build openjdk9.sif docker-daemon://openjdk:9.0.1-11-slim
INFO: Build complete: openjdk9.sif
-rwxr-xr-x 1 wangjl wangjl 174M Sep 16 22:46 openjdk9.sif
(2)从 tar 文件生成 sif
$ docker save openjdk:9.0.1-11-slim -o jdk9.tar
$ singularity build openjdk9-v2.sif docker-archive://jdk9.tar
生成的文件大小一样,md5不同
3. 编译和运行
$ singularity run -B /home/wangjl/test:/app/ openjdk9.sif bash
Singularity> cd /app
Singularity> javac Hello.java
Singularity> java Hello
Hello world, from Java!
Singularity> exit
exit
$ ls -lht #注意所有人和组的区别
total 12K
-rw-rw-r-- 1 wangjl wangjl 427 Sep 16 15:45 Hello.class #在 Singularity 中生成的
-rw-r--r-- 1 root root 427 Sep 16 14:58 Hello.class2 #在docker中生成的,改名2
(2) 或者执行一行命令
$ singularity exec -B /home/wangjl/test:/app/ --workdir=/app /data/wangjl/openjdk9.sif bash -c "cd /app && ls -lth"
/usr/bin/bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
total 12K
-rw-rw-r-- 1 wangjl wangjl 427 Sep 16 15:45 Hello.class
-rw-r--r-- 1 root root 427 Sep 16 14:58 Hello.class2
-rw-rw-r-- 1 wangjl wangjl 134 Sep 16 14:57 Hello.java
可见,地址输出是对的。不过设置工作目录无效。
$ singularity exec -B /home/wangjl/test:/app/ /data/wangjl/openjdk9.sif bash -c "cd /app && javac Hello.java && java Hello"
/usr/bin/bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
Hello world, from Java!
1.定义文件
$ cat nginx.def
Bootstrap: docker
From: nginx
Includecmd: no
%startscript
nginx
执行构建:
$ sudo singularity build nginx.sif nginx.def #必须使用root权限
-rwxr-xr-x 1 wangjl wangjl 50M Sep 16 16:54 nginx.sif
2. 测试,必须使用sudo权限
$ singularity instance start --writable-tmpfs nginx.sif web
$ curl localhost
curl: (7) Failed to connect to localhost port 80: Connection refused
#网页不能访问,curl也不行,可能默认的80端口被封了?测试发现,加sudo就好了。
$ singularity instance list
INSTANCE NAME PID IP IMAGE
web 3578 /home/wangjl/data/nginx.sif
$ singularity instance stop web
3. 修改配置文件,改端口,再次测试
查配置文件的位置
$ singularity shell nginx.sif
Singularity> cat /etc/nginx/conf.d/default.conf | grep -i root
root /usr/share/nginx/html;
Singularity> exit
exit
自定义配置文件:
$ cat nginx.config
server {
listen 8008;
listen [::]:8008;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
# list files
autoindex on;
autoindex_exact_size on;
autoindex_localtime on;
}
}
不加sudo访问不了。可能是网络、端口是系统资源,必须特权用户才能调用。
$ sudo singularity instance start -B /home/wangjl/data/nginx.config:/etc/nginx/conf.d/default.conf --writable-tmpfs nginx.sif web
$ sudo singularity instance list
INSTANCE NAME PID IP IMAGE
web 4457 /data/wangjl/nginx.sif
$ sudo singularity instance stop web
容器化技术必将是云时代不可或缺的技能之一,而 Docker 只是沧海一粟。随之而来的还有集群容器管理 K8s、Service Mesh 、Istio 等技术。打开 Docker 的大门,不断抽丝剥茧,逐层深入,你将感受到容器化的无穷魅力。
Kubernetes, also known as K8s, is an open-source system for automating deployment, scaling, and management of containerized applications.
https://kubernetes.io/ https://www.kubernetes.org.cn/k8s
1.临时文件夹 /tmp 装不下怎么办? $ TMPDIR=$PWD singularity build openjdk9-V2.sif docker-archive://jdk9.tar #能改变临时文件夹位置的命令 https://www.cnblogs.com/getbird/p/11650467.html https://www.docker.org.cn/docker/docker-206.html