Docker 学习
前言: 因为写项目时需要用到mysql
postgres``mongodb``redis
一些数据库 不想再自己电脑上安装这些 使用率不是很多 就想到了docker, 无论在服务器还时自己的电脑上, 感觉docker更符合我的场景
# Docker安装及使用教程 (opens new window)
# 卸载docker
1. 先查询下docker: yum list installed|grep docker ,然后执行卸载命令:yum -y remove docker.x86_64 docker-client.x86_64 docker-common.x86_64
2. 执行删除已存在的镜像和容器(以实际情况而定): rm -rf /var/lib/docker
# 删除相关组件
# 如果使用种方式的话,需要罗列全部使安装过的组件;
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
# 第二种方式,使用匹配符直接删除全部
# 推荐使用第二种方式,无需罗列所有的安装组件
yum remove docker docker-*
# 删除注册的服务
rm -rf /etc/systemd/system/docker.service.d
# 删除docker工作目录
rm -rf /var/lib/docker*
rm -rf /var/run/docker*
# 删除配置文件
# 直接清空这个文件夹,下面所有配置都将被清空
rm -rf /etc/docker
#----------------------------#
# /etc/docker/daemon.json #
# /ect/docker/key.json #
#----------------------------#
# 查找残留的docker
rpm -qa|grep docker
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 安装docker
# 第一步,需要安装一些依赖组件
# 安装所需的软件包。yum-utils 提供了 yum-config-manager,
# 并且 device mapper 存储驱动程序需要 device-mapper-persistent-data 和 lvm2。
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
# 使用以下命令来获得稳定的仓库
# 阿里云源地址速度相对比较快,这里是设置源地址为阿里云的镜像仓库地址。
# yum-config-manager \
# --add-repo \
# http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装 Docker Engine-Community
yum install -y docker-ce docker-ce-cli containerd.io
# 将当前用户添加到docker用户组
usermod -aG docker ${USER}
# Docker默认未启动,需要手动重启docker服务
systemctl restart docker
systemctl start docker
systemctl stop docker
# 切换当前会话到docker组
newgrp - docker
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# docker镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [ "https://fpr97nhz.mirror.aliyuncs.com" ]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
2
3
4
5
6
7
8
# Docker 入门教程 (opens new window)
# image 文件
# 列出本机的所有 image 文件。
$ docker image ls
# 删除 image 文件
$ docker image rm [imageName]
2
3
4
5
# 容器文件
# 列出本机正在运行的容器
$ docker container ls
# 列出本机所有容器,包括终止运行的容器
$ docker container ls --all
2
3
4
5
终止运行的容器文件,依然会占据硬盘空间,可以使用docker container rm
(opens new window)命令删除。
$ docker container rm [containerID]
# 实例
首先,运行下面的命令,将 image 文件从仓库抓取到本地。
$ docker image pull library/hello-world
上面代码中,docker image pull
是抓取 image 文件的命令。library/hello-world
是 image 文件在仓库里面的位置,其中library
是 image 文件所在的组,hello-world
是 image 文件的名字。
由于 Docker 官方提供的 image 文件,都放在library
(opens new window)组里面,所以它的是默认组,可以省略。因此,上面的命令可以写成下面这样。
$ docker image pull hello-world
抓取成功以后,就可以在本机看到这个 image 文件了。
$ docker image ls
现在,运行这个 image 文件。
$ docker container run hello-world
docker container run
命令会从 image 文件,生成一个正在运行的容器实例。
注意,docker container run
命令具有自动抓取 image 文件的功能。如果发现本地没有指定的 image 文件,就会从仓库自动抓取。因此,前面的docker image pull
命令并不是必需的步骤。
如果运行成功,你会在屏幕上读到下面的输出。
$ docker container run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
... ...
2
3
4
输出这段提示以后,hello world
就会停止运行,容器自动终止。
有些容器不会自动终止,因为提供的是服务。比如,安装运行 Ubuntu 的 image,就可以在命令行体验 Ubuntu 系统。
$ docker container run -it ubuntu bash
对于那些不会自动终止的容器,必须使用docker container kill
(opens new window) 命令手动终止。
$ docker container kill [containID]
# dockerFile
# GUI 工具
推荐使用 Portainer 作为容器的 GUI 管理方案。 推荐使用 Portainer 作为容器的 GUI 管理方案。
安装命令
docker volume create portainer_data
docker run -d -p ``8000``:8000 -p ``9000``:9000 --name``=``portainer --restart``=``always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce
# 常用命令汇总
# 查看docker基础信息
docker info
# 拉取镜像
docker pull <image>:<tag>
# 移除容器
docker rm <containerId>
# 移除镜像
docker rmi <imageId>
# 启动、停止、重启容器
docker stop <containerId>
docker start <containerId>
docker restart <containerId>
docker run -itd --name <imageName> -P/-p<port>:<port> <imageName> /bin/bash
# 查看docker容器
docker ps <-a>
# 打包镜像
docker tag <path>/<name> <remotePath>/<name>
docker push <remotePath>/<name>
# 登录docker
docker login <remoteIp>
# 进入容器内部
docker exec -it <containerId> /bin/bash
# 从仓库搜索镜像
docker search <imageName>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
(1)docker container start
前面的docker container run
命令是新建容器,每运行一次,就会新建一个容器。同样的命令运行两次,就会生成两个一模一样的容器文件。如果希望重复使用容器,就要使用docker container start
命令,它用来启动已经生成、已经停止运行的容器文件。
$ docker container start [containerID]
(2)docker container stop
前面的docker container kill
命令终止容器运行,相当于向容器里面的主进程发出 SIGKILL 信号。而docker container stop
命令也是用来终止容器运行,相当于向容器里面的主进程发出 SIGTERM 信号,然后过一段时间再发出 SIGKILL 信号。
$ bash container stop [containerID]
这两个信号的差别是,应用程序收到 SIGTERM 信号以后,可以自行进行收尾清理工作,但也可以不理会这个信号。如果收到 SIGKILL 信号,就会强行立即终止,那些正在进行中的操作会全部丢失。
(3)docker container logs docker container logs
命令用来查看 docker 容器的输出,即容器里面 Shell 的标准输出。如果docker run
命令运行容器的时候,没有使用-it
参数,就要用这个命令查看输出。
$ docker container logs [containerID]
(4)docker container exec docker container exec
命令用于进入一个正在运行的 docker 容器。如果docker run
命令运行容器的时候,没有使用-it
参数,就要用这个命令进入容器。一旦进入了容器,就可以在容器的 Shell 执行命令了。
$ docker container exec -it [containerID] /bin/bash
exit
容器停止退出
crtl+p+q
容器不停止退出
(5)docker container cp docker container cp
命令用于从正在运行的 Docker 容器里面,将文件拷贝到本机。下面是拷贝到当前目录的写法。
$ docker container cp [containID]:[/path/to/file] .
# 命令行技巧
# 删除所有镜像
docker rmi -f $(docker images -qa)
# 停用全部运行中的容器
docker stop $(docker ps -q)
# 删除所有的容器
docker rm $(docker ps -aq)
# 停用并删除所有容器
docker stop $(docker ps -q) & docker rm $(docker ps -aq)
删除所有为运行的容器 使用linux命令
docker container ls -f status-exited | awk '${print$1}' | awk 'NR>1' | xargs docker container rm
批量启动容器 使用docker命令
docker container ls -q -f status=created
查找所有状态为created的容器 并获取其IDdocker container start $(docker container ls -q -f status=created)
# docker配置
# /etc/docker/daemon.json
{
"authorization-plugins": [],//访问授权插件
"data-root": "",//docker数据持久化存储的根目录
"dns": [],//DNS服务器
"dns-opts": [],//DNS配置选项,如端口等
"dns-search": [],//DNS搜索域名
"exec-opts": [],//执行选项
"exec-root": "",//执行状态的文件的根目录
"experimental": false,//是否开启试验性特性
"storage-driver": "",//存储驱动器
"storage-opts": [],//存储选项
"labels": [],//键值对式标记docker元数据
"live-restore": true,//dockerd挂掉是否保活容器(避免了docker服务异常而造成容器退出)
"log-driver": "",//容器日志的驱动器
"log-opts": {},//容器日志的选项
"mtu": 0,//设置容器网络MTU(最大传输单元)
"pidfile": "",//daemon PID文件的位置
"cluster-store": "",//集群存储系统的URL
"cluster-store-opts": {},//配置集群存储
"cluster-advertise": "",//对外的地址名称
"max-concurrent-downloads": 3,//设置每个pull进程的最大并发
"max-concurrent-uploads": 5,//设置每个push进程的最大并发
"default-shm-size": "64M",//设置默认共享内存的大小
"shutdown-timeout": 15,//设置关闭的超时时限(who?)
"debug": true,//开启调试模式
"hosts": [],//监听地址(?)
"log-level": "",//日志级别
"tls": true,//开启传输层安全协议TLS
"tlsverify": true,//开启输层安全协议并验证远程地址
"tlscacert": "",//CA签名文件路径
"tlscert": "",//TLS证书文件路径
"tlskey": "",//TLS密钥文件路径
"swarm-default-advertise-addr": "",//swarm对外地址
"api-cors-header": "",//设置CORS(跨域资源共享-Cross-origin resource sharing)头
"selinux-enabled": false,//开启selinux(用户、进程、应用、文件的强制访问控制)
"userns-remap": "",//给用户命名空间设置 用户/组
"group": "",//docker所在组
"cgroup-parent": "",//设置所有容器的cgroup的父类(?)
"default-ulimits": {},//设置所有容器的ulimit
"init": false,//容器执行初始化,来转发信号或控制(reap)进程
"init-path": "/usr/libexec/docker-init",//docker-init文件的路径
"ipv6": false,//开启IPV6网络
"iptables": false,//开启防火墙规则
"ip-forward": false,//开启net.ipv4.ip_forward
"ip-masq": false,//开启ip掩蔽(IP封包通过路由器或防火墙时重写源IP地址或目的IP地址的技术)
"userland-proxy": false,//用户空间代理
"userland-proxy-path": "/usr/libexec/docker-proxy",//用户空间代理路径
"ip": "0.0.0.0",//默认IP
"bridge": "",//将容器依附(attach)到桥接网络上的桥标识
"bip": "",//指定桥接ip
"fixed-cidr": "",//(ipv4)子网划分,即限制ip地址分配范围,用以控制容器所属网段实现容器间(同一主机或不同主机间)的网络访问
"fixed-cidr-v6": "",//(ipv6)子网划分
"default-gateway": "",//默认网关
"default-gateway-v6": "",//默认ipv6网关
"icc": false,//容器间通信
"raw-logs": false,//原始日志(无颜色、全时间戳)
"allow-nondistributable-artifacts": [],//不对外分发的产品提交的registry仓库
"registry-mirrors": [],//registry仓库镜像
"seccomp-profile": "",//seccomp配置文件
"insecure-registries": [],//非https的registry地址
"no-new-privileges": false,//禁止新优先级(??)
"default-runtime": "runc",//OCI联盟(The Open Container Initiative)默认运行时环境
"oom-score-adjust": -500,//内存溢出被杀死的优先级(-1000~1000)
"node-generic-resources": ["NVIDIA-GPU=UUID1", "NVIDIA-GPU=UUID2"],//对外公布的资源节点
"runtimes": {//运行时
"cc-runtime": {
"path": "/usr/bin/cc-runtime"
},
"custom": {
"path": "/usr/local/bin/my-runc-replacement",
"runtimeArgs": [
"--debug"
]
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# 更换镜像源
- 首先,修改配置文件
vi /etc/docker/daemon.json
"registry-mirrors": ["https//registry.docker-cn.com"]
然后,加载Docker配置
systemctl daemon-reload
最后,重启Docker服务就好了
systemctl restart docker.service
附: 国内的几个优秀的Docker源
- Docker中国区官方镜像 https://registry.docker-cn.com (opens new window)
- 网易蜂巢 http://hub-mirror.c.163.com (opens new window)
- 中国科技大学 https://docker.mirrors.ustc.edu.cn (opens new window)
- 阿里镜像 xxx.mirror.aliyuncs.com (需要注册,xxx代表你的账号)
- DaoCloud xxxx.m.daocloud.ip (需要注册,xxx代表你的账号)
# 原理
# CNM
CNM Drivers
# 容器内部网络空间是否与外面一致
在容器外ip a
查看容器内所有ip:``docker container exec ${containerName} ip a
#
#
# docker 微服务
#
# Nginx 容器教程 (opens new window)
# HTTP 服务
Nginx 的最大作用,就是搭建一个 Web Server。有了容器,只要一行命令,服务器就架设好了,完全不用配置。
$ docker container run \
-d \
-p 127.0.0.1:8080:80 \
--rm \
--name mynginx \
nginx
2
3
4
5
6
上面命令下载并运行官方的 Nginx image (opens new window),默认是最新版本(latest),当前是 1.13.9。如果本机安装过以前的版本,请删掉重新安装,因为只有 1.13.9 才开始支持 server push。 上面命令的各个参数含义如下。
-d
:在后台运行-p
:容器的80
端口映射到127.0.0.1:8080
--rm
:容器停止运行后,自动删除容器文件--name
:容器的名字为mynginx
# 映射网页目录
网页文件都在容器里,没法直接修改,显然很不方便。下一步就是让网页文件所在的目录/usr/share/nginx/html
映射到本地。
首先,新建一个目录,并进入该目录。
$ mkdir nginx-docker-demo
$ cd nginx-docker-demo
2
然后,新建一个html
子目录。
$ mkdir html
在这个子目录里面,放置一个index.html
文件,内容如下。
<h1>Hello World</h1>
接着,就可以把这个子目录html
,映射到容器的网页文件目录/usr/share/nginx/html
。
$ docker container run \
-d \
-p 127.0.0.1:8080:80 \
--rm \
--name mynginx \
--volume "$PWD/html":/usr/share/nginx/html \
nginx
2
3
4
5
6
7
打开浏览器,访问 127.0.0.1:8080,应该就能看到 Hello World 了。
# 使用的案例
- 创建mysql5.7
docker run -p 33306:3306 -e MYSQL_ROOT_PASSWORD=qq164165005 --name eggmysql -d mysql:5.7
# 在使用docker中遇到的问题&需求
# 问题
# Docker启动时的报错汇总 (opens new window)
- Failed to start Docker Application Container Engine.
修改/etc/docker/daemon.json这个文件
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
- docker.service failed.
- Failed to restart docker.service: Unit not found.
docker.service启动失败:Unit not found的原因及解决办法 删除/usr/lib/systemd/system/docker.service的[UNIT]里包含的docker.socket,然后systemctl daemon-reload,最后systemctl start docker.service,发现启动成功了。 类似情况 如果是类似的情况,缺少docker.socket,但是新版本需要docker.socket。有两种方法可以解决该问题:
- 可以卸载docker,再重新安装,即可出现docker.socket。或者
- 创建一个/usr/lib/systemd/system/docker.socket文件,然后systemctl daemon-reload,最后systemctl start docker.service,即可启动成功。
# 当构建完镜像启动容器时失败
在最后加上
sh -c "while true; do sleep 3600; done"
DockerFile 最后加入
ENTRYPOINT ["sh", "-c", " exec tail -f /dev/null"]
防止容器启动就退出, 用这个命令一直前台阻塞删除未启动的容器 重新构建镜像
进入容器
docker exec [contianerID] -it /bin/sh
查看文件类型 .sh 设置文件类型set ff="unix"
# permission denied
sudo docker image ls
sudo goupadd docker
sudo gpasswd -a ${USER} docker
sudo service docker restart
logout 重新登录下
# 运行node项目 自动退出
运行容器的时候 自动进入项目命令行交互界面敲击
docker run -it pptr-image bash
# 需求收集
# 容器中调用宿主机docker命令
https://blog.csdn.net/nanhavezhi/article/details/103079056 (opens new window) 在构建容器时加上docker的目录映射
-v /run/docker.sock:/var/run/docker.sock \
-v /bin/docker:/bin/docker
2
# 在容器外执行某个容器内的某个命令操作
命令如下 加上-c $cmd
sudo docker exec -it $DOCKER_ID /bin/bash -c 'cd /packages/detectron && python tools/train.py'