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