最近自学docker,下面将自己学的知识总结下,比较基础 但实用
声明:部分图片 来自互联网,如有侵权,请留言
Docker介绍
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。Docker 是 PaaS 提供商 dotCloud 开源的一个基于 LXC 的高级容器引擎(windows上的docker 是要通过virtual boxi虚拟Linux内核才能实现),基于go语言并遵从Apache2.0协议开源。
Docker的应用场景
引用自:https://linux.cn/article-4612-1.html(这篇文章也有介绍docker的应用场景的,可以参考参考)
Docker的应用场景:面向产品、开发、测试、运维、自动化、微服务、大规模的分布式(微信红包 节点增加)
1,简化配置(开发、测试、预发布、灰度发布)
2,提高开发效率(部署开发环境)
3,进行应用隔离
4,服务器业务的整合
5,多租赁(多个人的容器 放在一起)
6,代码流水线
7,开发的调试
8,自动化扩容
9,Docker更适合微服务(SOA下 小的服务)
10,可以多版本测试
注意:同时启动大量虚拟机,会出现IO风暴的问题(和虚拟机一样),分布式的文件系统除外。
Docker安装
Centos 7 上 安装启动
# yum -y install docker
# systemctl enable docker
# systemctl start docker
安装很简单 网上基础的帖子还是蛮多的
Docker镜像
搜索镜像
# docker search centos
拉取镜像(使用aliyun的docker加速器,见《使用阿里云docker镜像加速器 加速国内获取Docker官方镜像》)
# docker pull centos
查看镜像
# docker images
Docker容器管理
启动容器,执行一个Hello world
# docker run centos /bin/echo 'Hello world!'
Hello world!
查看容器
# docker ps -a
没给docker容器起名字的时候,会自动的docker名字库里面 用一个名字
给容器起个名字,并进入容器中
# docker run --name mysocker -it centos /bin/bash
检查本地镜像中是否有centos镜像,没有的话 自动pull 再运行
–name 指定名称
-i 让容器的输入终端保持打开状态
-t 将容器的终端绑定到当前的终端
-h 指定容器系统的主机名
强制删除容器(不建议使用)
docker rm -f
审核的原因就是要防止意外(sql 脚本、shell脚本等 都要 自己审核一遍,特别是线上的)
启动容器后,会分配一个文件系统在系统之上。
还会给机器分配一个IP地址
# yum -y install net-tools
在运行 指定的一个应用程序,命令运行完,就会退出
启动已经终止的容器
# docker start 09619ddcb230(指定容器ID或容器名)
退出时间是刚刚,说明是启动过了的
后台运行容器
# docker run -d --name mynginx nginx
296f2dd3f36c1807173ebb20b46fb758332c571ad9f1405c0a2be7862a92275f
-d 后台启动容器
返回的一串是容器ID
删除容器
#docker rm 容器ID
运行在的容器 要先将容器停止( docker stop 容器ID),再删除
查看最后运行的容器
# docker ps -l
进入运行中的容器中
# docker attach 296f2dd3f36c
这个工具的问题,可能进不去,卡住的话按Ctrl+c,但是按Ctrl+c,容器也就退出了
所以就用另外的一个工具 nsenter
若没有,安装 # yum -y install util-linux
使用方法:
1,先启动之前退出了的 mynginx 容器
# docker start 296f2dd3f36c
2,获取 mynginx 容器的PID
# docker inspect --format "{{.State.Pid}}" mynginx
9345
3,进入运行中的 mynginx
# nsenter --target 9345 --mount --uts --ipc --net --pid
再用exit 退出,就只是 logout,容器没有停止
不建议用SSH
4,通过上面的步骤,写一个脚本,接容器名称或ID就可以进入运行中的容器。
脚本:
# cat into_running_container.sh
#!/bin/bash
#USAGE: sh into_running_container.sh container_id/container_name
nsenter --target $(docker inspect --format "{{.State.Pid}}" $1) --mount --uts --ipc --net --pid
使用:
# ./into_running_container.sh mynginx
root@296f2dd3f36c:/#
5,加入连接到 /bin 下使用
# ln -s /root/into_running_container.sh /bin/
# ll /bin/into_running_container.sh
lrwxrwxrwx 1 root root 31 Mar 7 17:50 /bin/into_running_container.sh -> /root/into_running_container.sh
# into_running_container.sh mynginx
root@296f2dd3f36c:/# exit
logout
Docker的网络访问
查看 网桥 用 brctl 命令,没有的就安装
# yum -y install bridge-utils
查看本机的网桥
# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02422c99a9e7 no vetha6cadd0
查看宿主机的ip
在容器中查看 容器的网络 路由
root@296f2dd3f36c:/# ip ro li
default via 172.17.0.1 dev eth0 #(网关是172.17.0.1 )
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2
随机映射:
# docker run -d -P --name mynginx1 nginx
f303caea9a3dde770e8712491bcb87589a2381f0dd6af57cb515a310820bfc6a
# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f303caea9a3d nginx "nginx -g 'daemon off" 33 seconds ago Up 32 seconds 0.0.0.0:32769->80/tcp, 0.0.0.0:32768->443/tcp mynginx1
随机把宿主机的32769端口映射到容器 mynginx1 的80端口,把宿主机的32768映射到 mynginx1 的443 端口。
在浏览器中访问宿主机的32769端口 就可以访问 mynginx1 容器的nginx
随机映射 好处是不用担心端口会冲突,不好的地方是 生产中还要使用别的手段获取端口
指定映射:
# docker run -d -p 91:80 --name mynginx2 nginx
59661c0d8dbe4b5188afe99469166440f766baccc8e33803fe0ad674d0f0213e
# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
59661c0d8dbe nginx "nginx -g 'daemon off" 3 seconds ago Up 2 seconds 443/tcp, 0.0.0.0:91->80/tcp mynginx2
上面把宿主机的 91 端口,映射到 容器 mynginx2 的 80 端口上,容器 mynginx2 的 443 端口没有指定映射端口,就没有被映射。
在浏览器中访问宿主机的91端口 就可以访问 mynginx2 容器的nginx
-p 指定端口 可以指定多个,上面的5种都可以
Docker数据管理
Docker有两种数据存储方式
镜像是只读的,用镜像启动容器的时候,可以理解给镜像加了一成 可读写的 “壳”(感觉有点像,虚拟机里面的 连接克隆,引用原来的,新的改变写新的文件),把文件写在读写层 就会与磁盘隔了一层,效率 相应的肯定会降低。所以 要用 “卷”,直接将容器中的要写的文件 直接写在磁盘上
数据卷:绕过 读写层、可以共享、及时生效。直接写到宿主机的磁盘上
启动一个容器 并 挂载一个数据卷
# docker run -it --name volume-test1 -h nginx -v /data centos
查看挂载的容器的数据卷在宿主机上的位置
docker inspect -f {{.Config.Volumes}} volume-test1
出现错误的时候 解决方案 见 :
《查看Docker 数据卷 映射的目录出错 1 2 executing at .Volumes map has no entry for key V》
指定的容器目录 和 宿主机 实现 数据卷挂载
[root@ops-ip-statistic ~]# docker run -it --name volume-test2 -h nginx -v /opt:/opt centos
[root@nginx /]# ll /opt/
total 0
drwxr-xr-x 2 root root 6 Feb 11 14:30 Docker
-v src:dst 注意:目录后面 不能带 “/”
应用案列:
直接在宿主机上写好 log/, conf/, …目录,映射到容器
但这样的在Dockerfile中使用不了,因为 Docker 人家的初衷是 一处构建,多处使用
Docker 存储的短板,日志 不好办。所以 把容器的日志目录 映射 到宿主机上。
挂载 数据卷 为只读(容器里面 不能写)
# docker run -it --name volume-test2 -h nginx -v /opt:/opt:ro centos
数据卷容器:
启动一个容器 使用其他容器的数据卷(不管那个容器是启动 还是关闭的)
[root@ops-ip-statistic ~]# docker run -it --name volume-test4 --volumes-from volume-test1 centos
[root@7b2770abfd30 /]# ls /data/
a hehe
Docker镜像构建
手动构建:
重点内容
编译安装nginx
1,# docker pull centos
2,# docker run --name nfinx-man -it centos
3,编译安装nginx
[root@4ebbccdeba3f /]# yum -y install wget gcc gcc-c++ make openssl-devel pcre-devel
[root@4ebbccdeba3f /]# wget http://nginx.org/download/nginx-1.11.10.tar.gz
[root@4ebbccdeba3f /]# mv nginx-1.11.10.tar.gz /usr/local/src/
[root@4ebbccdeba3f /]# cd /usr/local/src/
[root@4ebbccdeba3f src]# tar zxf nginx-1.11.10.tar.gz
[root@4ebbccdeba3f nginx-1.11.10]# useradd -s /sbin/nologin -M www
[root@4ebbccdeba3f nginx-1.11.10]# ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-http_stub_status_module --with-pcre
[root@4ebbccdeba3f nginx-1.11.10]# make
[root@4ebbccdeba3f nginx-1.11.10]# make install
4,设置nginx开机启动(通过镜像启动容器,nginx就启动)
直接通过
echo ‘/usr/local/nginx/sbin/nginx’>/etc/rc.local
来设置开机启动,这种方法是不行的。
因为容器中的程序 只有在前台运行 ,对外看来 才能运行,后台运行程序 是运行不了的。
所以,在nginx的的配置 里面,把默认的后台运行,关闭。
[root@4ebbccdeba3f nginx-1.11.10]# vi /usr/local/nginx/conf/nginx.conf
在最上面 添加 daemon off;
再
echo ‘/usr/local/nginx/sbin/nginx’>/etc/rc.local
来设置开机启动
5,退出容器
[root@4ebbccdeba3f nginx-1.11.10]# exit
6,保存容器为镜像
# docker commit -m "my nginx" 4ebbccdeba3f door/my-nginx:v1
sha256:28bccf4cf573817e2ef8f59ac94af3e642cc599277b9a1b9a7cf5f5688d54d77
查看保存的镜像
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
door/my-nginx v1 28bccf4cf573 About a minute ago 380.7 MB
运行构建的容器
# docker run -d -p 92:80 door/my-nginx:v1
发现容器 启动之后就退出了 所以,可见 把启动nginx的 命令放在 /etc/rc.local 中是不行的,再次进入容器,删除 rc.local 中的那一条,退出
# docker commit -m "v2" 7132903fc382 door/my-nginx:v2
sha256:52592de3ab22036bffe13b058f8d4031be60c8467c51765b4b86c5e5a1c31707
启动容器的时候 启动nginx:
# docker run -d -p 92:80 door/my-nginx:v2 /usr/local/nginx/sbin/nginx
c69d73bb6be83f5f4b4159f15a99107efc0c901a50b70e27754e9d180d9f0e73
可行!
Dockerfile构建:
主要的4部分:
- 基础镜像信息
- 维护者信息
- 镜像操作指令
容器启动时执行的指令
创建存Dockerfile 及其相关文件 的文件夹
# mkdir /opt/docker-file/nginx -p
[root@ops-ip-statistic nginx]# cat Dockerfile
# This is My first Dockerfile
# Version 1.0
# Author: Hailiang He
#Base images
FROM centos
#MAINTAINER
MAINTAINER Hailiang He
#ADD(如果是压缩包,拷贝过去会自动解压)
ADD nginx-1.11.10.tar.gz /usr/local/src
#RUN
RUN yum -y install wget gcc gcc-c++ make openssl-devel pcre-devel
RUN useradd -s /sbin/nologin -M www
#WORKDIR
WORKDIR /usr/local/src/nginx-1.11.10
RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-http_stub_status_module --with-pcre && make && make install
RUN echo "daemon off;" >>/usr/local/nginx/conf/nginx.conf
ENV PATH /usr/local/nginx/sbin:$PATH #(环境变量)
EXPOSE 80
CMD ["nginx"]
用 Dockerfile 构建 镜像
[root@ops-ip-statistic nginx]# docker build -t nginx-file:v1 /opt/docker-file/nginx/
[root@ops-ip-statistic nginx]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx-file v1 67071da29a27 About a minute ago 379.8 MB
Docker 资源隔离
使用Linux的LXC 技术
资源限制 使用 cgroup
CPU 内存 (磁盘现在还不行)
压力测试工具 stress 见:http://blog.sina.com.cn/s/blog_5f50a4c80101pdik.html
写Dockerfile 源码安装stress(centos7 yum没有)
# docker run -it --rm stress --cpu 1
-c CPU配额,默认是1024(一个容器的话就是默认可以使用100%的CPU,两个容器都是1024的话,就是各50%)
–rm 容器运行完成自动删除
–cpu 指定cpu个数
# top
查看stress 占用的CPU 比率
再另一个窗口
# docker run -it --rm stress --cpu 1
# top
查看两个stress 占用的CPU 比率
Ctrl+c
退出
再另一个窗口
# docker run -it --rm stress --cpu 1 -c 512
# top
查看两个stress 占用的CPU 比率
–cpuset-cpus 指定在第几个cpu上跑 (top 按 1即可看到每个cpu的占用比)
-m 指定 容器 最多使用多少内存
# docker run -it --rm -m 128m stress --vm 1 --vm-bytes 256m --vm-hang 0
测试 给 128M内存的容器 压256 M的测试,容器就挂了,不能超过 2 倍
Docker 的网络模式
桥接模式(默认)
宿主机 在本地会有一个docker0 就像vmware的 VMnet1、VMnet8 一样
可查看本地的虚拟网桥
这个虚拟网桥的接口 是启动一个容器就有1对的,一个在宿主机上,一个在容器上
docker默认的网段是172.xxx 段
iptable -nat -L -n
查看 docker的上网方式是通过 dnat 实现的
Host 模式
直接和物理机 用同一个堆栈,ip、端口 都是用同一个的,比如 宿主机 用了 80端口,容器 就不能用80 端口了
使用另一个容器的网络
可以用namespace 绑定端口
Docker-compose
可以实现,一次构建多个 镜像,启动多个容器 如 一个lnmp架构的容器组
Docker 私有仓库
# docker pull registry
# docker run -d -p 5001:5000 registry
先要 打tag 再push
# docker tag 67071da29a27 10.1.61.102:5001/test/nginx-file:v1
使用带“-”的镜像名称 可能会显示没有 也可以直接用image id
# docker push 10.1.61.102:5001/test/nginx-file:v1
push 出现报错:
The push refers to a repository [10.1.61.102:5001/test/nginx-file]
Get https://10.1.61.102:5001/v1/_ping: http: server gave HTTP response to HTTPS client
解决方法:
在”/etc/docker/“目录下,创建”daemon.json“文件。在文件中写入:
{
"insecure-registries":["192.168.1.100:5000"]
}
可行!http://www.cnblogs.com/lin1/p/6207348.html
淘宝加速的连接,也是利用这个文件
"registry-mirrors": ["https://oepq5dcw.mirror.aliyuncs.com"]
在使用该 docker镜像仓库的docker服务器上也要改
# cat /etc/docker/daemon.json
{
"insecure-registries":["10.1.61.102:5001"]
}
拉取 自己的镜像仓库的 镜像
# docker pull 10.1.61.102:5001/test/nginx-file:v1
这个问题可能是由于客户端采用https,docker registry未采用https服务所致。一种处理方式是把客户对地址“10.1.61.102:5001”请求改为http。
更好的解决方法是,利用nginx 配置https 进行中转,就不需要上面哪些麻烦的更改了
Docker WEB界面 shipyard
现在都是 开发 测试 方面 为了方便使用的
第一步:
docker 监听的模式 加上tcp
centso6上安装的 在 /etc/sysconfig/docker
的other_args
上添加:
-H tcp://0.0.0.0:235 -H unix:///var/run/docker.sock
centos7网上 的 实在 /usr/lib/systemd/system/docker.service
的 ExeStart
后面加
centos7上的 我尝试在 OPTIONS
后面 加上面一串 参数
注意:docker服务 在重启服务的时候 容器就会down
第二部:
按照 官网上的步骤 一步来
https://www.shipyard-project.com/docs/deploy/manual/
就OK了
<ip-of-host>
填自己宿主机的IP(如:10.1.61.102)
完成之后 访问:http://10.1.61.102:8080
登陆,默认账号 密码是 admin/shipyard,登进去了 如下图: