docker
一、初步了解docker
1、什么是容器?
容器就是在隔离的环境中运行的一个进程。进程如果停止,容器就会销毁。隔离的环境拥有自己的系统文件(/根下的东西就叫系统文件),ip地址,主机名等,特别像虚拟机。
2、容器和虚拟化的区别(从启动流程分析)
linux开机启动流程: 当按下电源按钮时,系统会进行bios开机硬件自检,扫描计算机硬件,若硬件有问题就不会往下进行了,一旦开机自检通过,老式电脑会滴的一声。根据bios设置的优先启动项boot,网卡,硬盘,u盘,光驱,读取mbr信息,0柱面,0磁头,1扇区,mbr里有引导信息,引导信息会加载grub启动菜单(有每个操作系统的内核路径),根据内核路径加载内核,启动第一个进程/sbin/init(Centos
6) systemd(Centos 7),第一个进程会把其余的子进程拉起来,最终操作系统就启动完成了,运行服务。容器启动流程: 容器共用宿主机的内核,第一个进程不是系统的第一个进程,容器的第一个进程直接就是跑的服务(nginx,httpd,mysql)。
总结:
容器共用宿主机内核,更加的轻量级,损耗少,启动快,性能高,只能运行linux系统。
虚拟机:需要硬件的支持,需要模拟硬件,需要走开机启动流程,可以进行不同的操作系统。
3、什么是docker?
docker是容器的管理工具,就相当于libvirt是kvm虚拟机的管理工具一样,docker是一种软件的打包技术,docker的主要目标是’build,ship and run any app,anywhere’构建,运输,处处运行。docker解决了软件和操作系统环境之间的依赖,使应用程序可以在几乎任何地方以相同的方式运行,开发人员在自己笔记本上创建并测试好的容器,无需任何修改就能够在生产系统的虚拟机,物理服务器或公有云主机上运行。
4、docker的主要组件
主要组件有:镜像,容器,仓库,网络,存储
启动容器必须要有一个镜像,仓库中只存储镜像
容器- - -镜像- - -仓库
二、docker的安装
1、系统要求
Docker 支持 64 位版本 CentOS 7/8,并且要求内核版本不低于 3.10,uname -r看内核版本。
2、使用yum安装
yum install yum-utils -y
鉴于国内网络问题,强烈建议使用国内源,执行下面的命令添加yum软件源
yum-config-manager --add-repo \ https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
更新 yum 软件源缓存,并安装 docker-ce
yum install docker-ce docker-ce-cli containerd.io
启动 Docker
systemctl start docker
systemctl enable docker
3、验证docker是否安装成功
使用docker version有client和service两部分表示docker安装启动都成功了
三、启动第一个容器
1、docker info,可以查看容器状态,以及宿主机的版本及内存,如果要做监控可以用到
2、配置镜像加速文件
[root@docker ~]# cat /etc/docker/daemon.json
{
"registry-mirrors": [
"https://sopn42m9.mirror.aliyuncs.com",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
]
}
再进行docker重启
[root@docker ~]# systemctl daemon-reload
[root@docker ~]# systemctl restart docker
启动第一个容器,现在用docker来安装nginx
[root@docker ~]# docker run -d -p 80:80 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
命令解释:
run 创建并运行一个容器
-d 放在后台
-p 端口映射
nginx docker镜像的名字
这时我们在浏览器访问就可以访问到nginx,我们查询进程时并没有这个进程,这就是docker的隔离环境运行的进程
[root@docker ~]# netstat -tupln|grep nginx
[root@docker ~]#
四、docker的镜像管理命令
1、搜索镜像
[root@docker ~]# docker search centos
也可以在仓库地址搜:hub.docker.com
2、从官方仓库下载镜像
[root@docker ~]# docker pull alpine
alpine是最小的linux镜像,只有5M
私有仓库就有镜像的域名,最后才有镜像的名称和版本,举例如下
[root@docker ~]# docker pull daoclound.io/huangzhichong/alpine-cn:latest
3、查看镜像列表
[root@docker ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest 6dbb9cc54074 3 weeks ago 5.61MB
nginx latest 62d49f9bab67 3 weeks ago 133MB
4、删除镜像
[root@docker ~]# docker image rm alpine
rm后可以加镜像名,也可以加id,正在使用的镜像无法删除哦
5、导出镜像
[root@docker ~]# docker image save -o /opt/docker_alpine.tar.gz alpine:latest
[root@docker ~]# ll -h /opt/docker_alpine.tar.gz
-rw------- 1 root root 5.7M 5月 7 15:32 /opt/docker_alpine.tar.gz
#也可以直接重定向代替-o参数
[root@docker ~]# docker image save >/opt/docker_alpine.tar.gz alpine:latest
6、删除镜像,因为我们现在已经把它导出了,可以放心的删除
[root@docker ~]# docker image rm alpine:latest
Untagged: alpine:latest
Untagged: alpine@sha256:69e70a79f2d41ab5d637de98c1e0b055206ba40a8145e7bddb55ccc04e13cf8f
Deleted: sha256:6dbb9cc54074106d46d4ccb330f2a40a682d49dda5f4844962b7dce9fe44aaec
Deleted: sha256:b2d5eeeaba3a22b9b8aa97261957974a6bd65274ebd43e1d81d0a7b8b752b116
[root@docker ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 62d49f9bab67 3 weeks ago 133MB
7、导入镜像
[root@docker ~]# docker image load -i /opt/docker_alpine.tar.gz
b2d5eeeaba3a: Loading layer 5.88MB/5.88MB
Loaded image: alpine:latest
[root@docker ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest 6dbb9cc54074 3 weeks ago 5.61MB
nginx latest 62d49f9bab67 3 weeks ago 133MB
五、docker的容器管理命令
1、创建并运行一个容器,-it表示进入到这个容器docker run=docker create + docker start
[root@docker ~]# docker run -it centos6.9
命令解释:
-i:以交互模式运行容器,通常与 -t 同时使用;
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用
centos6.9 容器的名字
2、查看处于运行状态的容器,docker container ls=docker ps,加上-a参数列出所有状态的容器
[root@docker ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b28872446ef nginx "/docker-entrypoint.…" About an hour ago Up About an hour 0.0.0.0:80->80/tcp, :::80->80/tcp flamboyant_austin
3、停掉启动的容器
[root@docker ~]# docker stop 5b28872446ef
5b28872446ef
[root@docker ~]# docker ps #再次进行查看,已经没有运行的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4、启动容器
[root@docker ~]# docker container start 5b28872446ef
5b28872446ef
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b28872446ef nginx "/docker-entrypoint.…" About an hour ago Up 2 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp flamboyant_austin
5、进入容器(调试,排错)
进入到上面列表列出的容器
[root@docker ~]# docker container exec -it 5b28872446ef /bin/bash
root@5b28872446ef:/#
在容器里进行的一系列操作都在宿主机里可以看到,首先我们要先在宿主机安装pstree
[root@docker ~]# yum install -y psmisc-22.20-17.el7.x86_64
然后在容器里执行sleep 1000,在宿主机里执行pstree就可以看到容器的活动了
在容器里执行
root@5b28872446ef:/# sleep 1000
6、删除容器
[root@docker ~]# docker rm 0d946eee236f
0d946eee236f
用docker ps -a 可以查到容器的ID号
批量删除容器
[root@docker ~]# docker ps -a -q #-q静默输出id号
8506acb4b119
94b6c33b2211
5ecf5d5921db
5b28872446ef
[root@docker ~]# docker rm `docker ps -a -q` #这样删除所有容器的Id号
8506acb4b119
94b6c33b2211
5ecf5d5921db
Error response from daemon: You cannot remove a running container 5b28872446efd01064b99e9f700d2a373ae4814f0172314624f56ced852abefc. Stop the container before attempting removal or force remove
#提示运行的容器无法删除,可以停止此容器或者强制删除,下面选取强制删除-f这种方式
[root@docker ~]# docker rm -f `docker ps -a -q`
5b28872446ef
六、docker容器的网络访问
1、单个容器使用80端口
进入到一个容器,查看它的IP地址
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STA TUS PORTS NAMES
982c20052f66 nginx:latest "/docker-entrypoint.…" About a minute ago Up About a minute 80/tcp gifted_montalcini
[root@docker ~]# docker exec -it 982c20052f66 /bin/bash
root@982c20052f66:/# hostname -i
172.17.0.2
此IP地址在宿主机可以访问,但是在浏览器上却不能访问。
[root@docker ~]# curl -I 172.17.0.2
HTTP/1.1 200 OK
Server: nginx/1.19.10
Date: Fri, 07 May 2021 09:03:12 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 13 Apr 2021 15:13:59 GMT
Connection: keep-alive
ETag: "6075b537-264"
Accept-Ranges: bytes
那么在生产中这样是不行的,要想通过浏览器访问就得做端口映射,用以下命令,-p 宿主机端口:容器端口
[root@docker ~]# docker run -d -p 80:80 nginx
c21acf6bbb1cdac6bbe37b14387837ef8c495c82eb9a709b5bdd6308a4f9a7
这时系统就自动修改了iptables规则
[root@docker ~]# iptables -t nat -L -n
...
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
MASQUERADE tcp -- 172.17.0.3 172.17.0.3 tcp dpt:80
从容器80端口出来的都模拟成宿主机的IP地址
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17 .0.3:80
做了地址转换,当访问宿主机的任何一个80端口都转到容器里面来
浏览器访问宿主机的IP就可以访问到nginx页面了。
2、多个容器同时使用80端口
设置两个网卡,ens33(192.168.119.166),ens34(192.168.119.168)
在运行容器时可以指定不用的IP地址
[root@docker ~]# docker run -d -p 192.168.119.166:80:80 nginx:latest
[root@docker ~]# docker run -d -p 192.168.119.168:80:80 nginx:latest
遇到的问题:
在创建容器时可能会出现以下错误,这是IPv4转发已禁用。网络将不起作用,所以我们开启ipv4转发就好了,具体命令如下
[root@docker ~]# docker run -d -p 192.168.119.168:80:80 nginx:latest
WARNING: IPv4 forwarding is disabled. Networking will not work.
解决办法如下再次创建容器就好了:
[root@docker ~]# echo "net.ipv4.ip_forward=1" >> /usr/lib/sysctl.d/00-system.conf
[root@docker ~]# tail -2 /usr/lib/sysctl.d/00-system.conf
net.bridge.bridge-nf-call-arptables = 0
net.ipv4.ip_forward=1
[root@docker ~]# systemctl restart network
[root@docker ~]# systemctl restart docker
查看容器的运行列表,可以看到指向了两个不同的IP,同样的端口
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6a773adddf8 nginx:latest "/docker-entrypoint.…" 14 seconds ago Up 12 seconds 192.168.119.168:80->80/tcp eager_lamport
ad35963a76f3 nginx:latest "/docker-entrypoint.…" 7 minutes ago Up 7 minutes 192.168.119.166:80->80/tcp sleepy_bardeen
a45542d91833 nginx:latest "/docker-entrypoint.…" 6 minutes ago Created festive_khayyam
9dcf3223219d nginx:latest "/docker-entrypoint.…" 7 minutes ago Created beautiful_fermat
用netstat查看也是同样的结果
[root@docker ~]# netstat -tupln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 192.168.119.168:80 0.0.0.0:* LISTEN 9464/docker-proxy
tcp 0 0 192.168.119.166:80 0.0.0.0:* LISTEN 8419/docker-proxy
我们可以进入到容器里在/usr/share/nginx/html/index.html里设置不同的内容,在nginx页面访问就是不同的页面了
[root@docker ~]# docker exec -it aa7b710d2294 /bin/bash
root@aa7b710d2294:/# echo '166'> /usr/share/nginx/html/index.html
[root@docker ~]# docker exec -it 804b7502b4cf /bin/bash
root@804b7502b4cf:/# echo "168" > /usr/share/nginx/html/index.html
3、随机端口
[root@docker ~]# docker run -d -p 192.168.119.166::80 nginx:latest
15ec75d62312162316114c1259173c0cd869cc51104851d18524bb2dc4de0a5a
[root@docker ~]# netstat -tupln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 192.168.119.168:80 0.0.0.0:* LISTEN 10487/docker-proxy
tcp 0 0 192.168.119.166:80 0.0.0.0:*
tcp 0 0 192.168.119.166:49153 0.0.0.0:* LISTEN 10682/docker-proxy
可以看到最后一个端口是随机分配的
随机端口可以应用在下列情况中
也可以选择下面的方法来随机指定端口
docker run -P nginx
4、指定udp协议
使用宿主机的192.168.119.166这个IP地址的随机端口的udp协议映射容器的udp53端口
docker eun -p 192.168.119.166::53:udp
七、docker的数据卷管理
1、-v 宿主机的目录:容器的目录
具体命令如下:
[root@docker opt]# cd /data/
[root@docker data]# cat index.html
weclome to docker
[root@docker data]# docker run -d -p 81:80 -v /data/:/usr/share/nginx/html ngin x:latest
854843d96e7a882b264126fb0e62b34c27495c928f2912089ea8ab2fdcc43f4a
访问宿主机IP及端口号:
2、-v 数据卷名字:容器目录
[root@docker data]# docker run -d -p 82:80 -v test:/usr/share/nginx/html nginx:latest
32827ac1414acf3f4130badccb3ec91a2868face70f0f5ef95c4b2351a1a26a5
我们可以随便指定一个数据卷的名字,然后进行查看就可以看到数据卷的详细信息
[root@docker data]# docker volume ls
DRIVER VOLUME NAME
local test
[root@docker data]# docker volume inspect test
[
{
"CreatedAt": "2021-05-08T14:37:44+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/test/_data",
"Name": "test",
"Options": null,
"Scope": "local"
}
]
[root@docker data]# cd /var/lib/docker/volumes/test/_data
[root@docker _data]# ls
50x.html index.html
这两个文件是容器里的文件
然后访问宿主机IP及端口
八、手动制作docker镜像
1、启动一个基础镜像,让镜像实现ssh功能,制作单服务镜像
[root@docker ~]# docker run -it centos:centos6.9
echo '192.168.119.166 mirrors.aliyun.com' >>/etc/hosts
curl -o /etc/yum.repos.d/Centos-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
yum install openssh-server -y
/etc/init.d/sshd restart
2、将容器提交成镜像
[root@docker ~]# docker container commit d3d79bbdf011 centos6.9_ssh:v1 最后为镜像的名称和版本
sha256:b0231e19e6842bb7f5b78d557ea617ff638761da753f6e16788ff3787f69bf36
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos6.9_ssh v1 b0231e19e684 12 seconds ago 218MB
可以看到创建的镜像
3、测试镜像的功能(即能启动服务,又能让服务一直在前台运行就加上最后一个参数)
docker run -d -p 1023:22 centos6.9_ssh:v1 /usr/sbin/sshd -D
九、dockerfile自动制作docker镜像
dockerfile常用格式
FROM 选择一个基础镜像,这个镜像的妈妈是谁
MAINTAINER 告诉别人,谁负责它(指定维护者信息,可以没有)
LABEL 描述,标签,也可以没有
RUN 安装软件,需要执行的命令(你想让它干啥)
ADD 给它点创业资金(会自动解压tar),制作docker基础的系统镜像
COPY 复制文件,不会解压tar包
WORKDIR 我是cd,今天化妆了(设置当前工作目录)
VOLUME 给它一个存放行李的地方(设置卷,挂载主机目录,将设置的目录持久化保存)
EXPOSE 它要打开的门是啥(指定对外的端口,-P 随机端口)
ENV 设置环境变量
CMD 指定容器启动后要干的事情
workdir的作用可以用下图解释,指定容器的初始目录
1、可以将上述的手动制作镜像搞成自动制作镜像
[root@docker ~]# cd /data/dockerfile
[root@docker ~]# mkdir centos6.9_ssh
[root@docker ~]# cd centos6.9_ssh
[root@docker ~]# cat dockerfile
FROM centos:6.9
RUN echo '192.168.119.166 mirrors.aliyun.com' >>/etc/hosts
RUN curl -o /etc/yum.repos.d/Centos-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
RUN yum install openssh-server -y
RUN /etc/init.d/sshd restart
EXPOSE 22
CMD ["/usr/sbin/sshd","-D"]
2、构建镜像
[root@docker ~]# docker build -t centos6.9_ssh:v2 .
.表示在当前目录读取dockerfile
3、运行容器
docker run -d -p 2022:22 centos6.9_ssh:v2
也可以用dockerfile做双服务的镜像,如ssh+nginx
[root@docker ~]# mkdir centos6.9_ssh_nginx
[root@docker ~]# cat dockerfile
FROM centos:6.9
RUN echo '192.168.119.166 mirrors.aliyun.com' >>/etc/hosts
RUN curl -o /etc/yum.repos.d/Centos-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
RUN curl -o /etc/yum.repos.d/epel.repo
http://mirrors.aliyun.com/repo/epel-6.repo
RUN yum install openssh-server nginx -y
RUN /etc/init.d/sshd restart
ADD init.sh /init.sh
EXPOSE 22 80
CMD ["/bin/bash","/init.sh"]
然后在当前目录下创建init.sh文件
#!/bin/bash
service sshd restart
nginx -g 'daemon off;'
然后构建镜像
[root@docker ~]# docker build -t centos6.9_ssh_nginx:v1 .
运行容器
docker run -d -p 2023:22 -p 80:80 centos6.9_ssh_nginx:v1
再进行测试,发现ssh登录和nginx访问都没有问题
docker镜像的分层(kvm链接克隆,写时复制的特性),优点:复用,节省磁盘空间,相同的内容只需加载一份到内存。
dockerfile的优化:
1、尽可能合并RUN指令,清理无用的文件(yum缓存,源码包)
2、尽可能选择体积小的linux,如alpine
3、把变化的内容放在dockerfile的结尾,前面的就用缓存