Docker
- 一. 容器的概念,作用
- 二. docker的安装部署
- 三. 镜像管理
- 四. 容器管理
- 五. 容器中数据永久保存、容器间共享数据、host与容器共享数据
- 六. docker save、export、load、import
- 七. 用commit,load,import生成镜像的区别
- 八. 基于容器制作新镜像
- 九. 用dockerfile制作镜像
- 十 制作私有registry仓库
- 十一 给本地仓库加安全认证
- 十二 发布镜像到docker hub
- 十三 发布镜像到阿里云
- 十四 网络
- 十五 docker图形化界面管理工具之portainer
- 十五 docker服务端开启端口提供外部访问
- 十五 镜像的分层结构
- 十六 docker machine
- 十七 docker 的监控
- 十八 Compose
- 18.1 安装
- 18.2 基本操作流程
- 18.3 docker-compse基本命令
- 18.4 compose file-docker-compose.yaml
- 18.5 compse中设置环境变量
- 18.4 在compost 文件中用关键字environment给某个容器定义环境变量,相当于docker run -e VARIABLE=VALUE ...
- 18.5 在compost 文件中用关键字environment给某个容器定义环境变量文件,相当于docker run --env-file=FILE ...![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/79d4fb41a9da68847522e7391ba1a85f.png#pic_center)
一. 容器的概念,作用
- 容器是为了隔离资源
- 容器技术的三大重点:
2.1 chroot
2.2 namespaces:资源隔离 - PID:进程隔离
- NET:网络接口管理
- IPC:进程间通信
- MNT:管理挂载点
- UTS:隔离内核和版本识别
2.3 CCgroups:控制每个namespace中的资源分配
二. docker的安装部署
1. 下载镜像源
curl http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
2. 安装依赖包
> yum install -y yum-utils device-mapper-persistent-data lvm2
> yum list docker-ce.x86_64 --showduplicates | sort -r
3. 安装docker-ce
yum install -y --setopt=obsoletes=0 \
docker-ce-17.03.2.ce-1.el7.centos.x86_64 \
docker-ce-selinux-17.03.2.ce-1.el7.centos.noarch
4. 启动docker服务
systemctl daemon-reload
systemctl restart docker
docker version
docker info
5. docker的体系结构
docker分三部分:
- 客户端程序:执行docker命令
- 服务端程序:驻留docker deamon;存放镜像;存放容器
- 镜像源:存放别人做好的镜像供下载
6. docker状态
7. docker所占磁盘空间
[root@master overlay]# docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 8 3 776.8 MB 776.8 MB (100%)
Containers 11 2 -2 B 0 B
Local Volumes 0 0 0 B 0 B
8. 自动清理磁盘空间(已停止的容器,未被任何容器所使用的卷,未被任何容器所关联的网络,所有悬空镜像)[root@master overlay]# docker system prune
WARNING! This will remove:
- all stopped containers
- all volumes not used by at least one container
- all networks not used by at least one container
- all dangling images
Are you sure you want to continue? [y/N]
三. 镜像管理
- 从源上搜索可用的镜像
docker search centos - 从源上下载镜像(冒号后面是要下载的版本,如果不填默认下载最新版 )
docker pull centos:6.9
docker pull centos:7.5.1804
docker pull nginx - 查询本机上已经下载的镜像‘’
docker images
docker images -q # 加一个q参数是只显示镜像id
docker inspect ID/name:tag # inspect是查看镜像的详细信息 - 从本地删除镜像
docker rmi IID
docker rmi `docker images -q` #删除所有镜像
docker rmi $(docker images -q)
5.导入导出镜像
[root@docker ~]# docker image save nginx >/opt/nginx.tar.gz
[root@docker ~]# docker image load -i /opt/nginx.tar.gz
四. 容器管理
4.1 启动容器
# 交互式启动容器
[root@docker ~]# docker run -it --name "testcentos" centos:6.9 /bin/bash
主要是针对于工具类的容器,一旦exit容器,容器就自动关闭
# 守护式启动
1.交互式启动的容器使用完后,用Ctrl+p+q退出会让容器还在底层活着
[root@docker ~]# docker run -it --name "testnginx" nginx /bin/bash
加ctrl+p+q
[root@docker ~]# docker attach testnginx
2.死循环
docker run --name testnginx1 -d nginx /bin/sh -c "while true ;do echo hello world; sleep 1;done"
3.服务前台运行
sshd -D
nginx -g ""
4.2 查看容器的cpu,内存,网络资源等使用情况
[root@andy ~]# docker container stats
4.3 run中的–entrypoint
等价于dockerfile中的
五. 容器中数据永久保存、容器间共享数据、host与容器共享数据
1. 容器中热数据的永久保存、host与容器共享数据
冷数据存储在镜像中;
热数据存储在容器中;
容器中的热数据在容器关闭后就丢失了;
要想把容器中的热数据永久保存需要用到host上的data volume;
把host中的data volume映射到容器中的目录或文件(不能映射到容器的dev)
data volume分为两种bind mount和managed volume
1.1 bind mount
是把host的目录或文件映射到容器
# v参数后面加host的路径
# 映射目录
docker run -d -p 80:80 -v ~/htdocs:/usr/local/test/htdocs httpd
# 映射文件
docker run -d -p 81:80 -v ~/htdocs/1.txt:/usr/local/test/htdocs/1.txt --name test1 httpd
1.2. managed volume
是把容器的目录或文件映射到主机
# v参数后不加host目录
docker run -d -p 82:80 -v /usr/local/test/htdocs --name test2 httpd
1.3. docker volume命令只能查看managed volume产生的数据卷,不能查看bind mount产生的数据卷
2. 容器间共享数据
容器间共享数据有两种方式:数据卷容器和data-packed volume container
2.1 数据卷容器 volume container
# volume container 是专门为其它容器提供 volume 的容器。
# volume container 提供的卷可以是 bind mount,也可以是 docker managed volume。
volume container 的优点:
# 与 bind mount 相比,不必为每一容器指定 host path,所有 path 都在 volume container 中定义好,容器只需要与 volume container 关联,从而实现容器与 host 的解偶。
# 第一步:建立一个数据卷容器,容器里面用v参数指定host目录与容器目录的映射关系
# 第二步:用刚刚建立的数据卷容器创建三个容器test1,2,3
数据卷容器的缺点:
- host上的数据丢失的话,数据就没了;
- 一台host主机的数据没法给另一台host主机用
2.2 data-packed volume container
2.2.1 基本介绍
(1)前面例子 volume container 的数据归根到底还是在 host 里,如果想要将数据完全放到 volume container 中,同时又能与其它容器共享可以使用 data-packed volume container。
(2)data-packed volume container 原理是将数据打包到镜像中,然后通过 docker managed volume 共享。
2.2.2 使用场景
由于 data-packed volume container 是自包含的,不依赖 host 提供数据,具有很强的移植性,非常适合只使用静态数据的场景。比如应用的配置信息、Web server 的静态文件等。
2.2.3 data-packed volume container 的创建
(1)首先我们创建一个 Dockerfile 文件用于构建镜像
内容如下:
FROM busybox:latest
ADD htdocs /usr/local/apache2/htdocs
VOLUME /usr/local/apache2/htdocs
内容说明:
第二行:ADD 将静态文件添加到容器目录 /usr/local/apache2/htdocs
第三行:VOLUME 作用与 -v 等效,用来创建 docker managed volume,mount point 为 /usr/local/apache2/htdocs。因为这个目录就是 ADD 添加的目录,所以会将已有数据复制到 volume 中。
(2)接着 build 这个镜像,命名为 datapacked
docker build -t datapacked
(3)最后用这个镜像创建 data-packed volume container 即可
docker create --name vc_data datapacked
(4)data-packed volume container 的创建
data-packed volume container 创建好之后,其它容器同样通过 --volumes-from 来使用它。比如下面三个 httpd 容器都使用了 vc_data。
docker run --name web1 -d --volumes-from vc_data httpd
docker run --name web2 -d --volumes-from vc_data httpd
docker run --name web3 -d --volumes-from vc_data httpd
六. docker save、export、load、import
1. save和load
save:
可以将一个或多个image打包为tar文件;
也可对容器进行save,但save的是容器背后的image;
save命令后面即可跟镜像也可跟容器,跟容器实际是找背后得镜像去save
load:
从save的tar向本地镜像库加载镜像,如果本地镜像库已经存在这两个镜像,将会被覆盖。
2. docker export和import
export:
用来讲容器的文件系统进行打包;
export后面要指定容器,不能指定镜像;
export得到的打包文件只能用import命令去生成镜像;
export的应用场景是制作基础镜像,比如你从一个ubuntu镜像启动一个容器,然后安装一些软件和进行一些设置后,使用docker export保存为一个打包文件,然后用import命令将这个打包文件制作为一个基础镜像。然后,把这个镜像分发给其他人使用,比如作为基础的开发环境。
import:将打包好的容器文件import到本地镜像仓库,同事可以指定新镜像的名字和tag
3. save和export的区别
总结一下docker save和docker export的区别:
- docker save保存的是镜像(image),docker export保存的是容器(container);
- docker load用来载入镜像包,docker import用来载入容器包,但两者都会恢复为镜像;
- docker load不能对载入的镜像重命名,而docker import可以为镜像指定新名称;
- save是保存一个镜像的所有层的内容;export只是保存容器的系统文件。
4. import和commit的区别
可以将docker import理解为将外部文件复制进来形成只有一层文件系统的镜像;
而docker commit则是将当前的改动提交为一层文件系统,然后叠加到原有镜像之上。
七. 用commit,load,import生成镜像的区别
1. commit
是将commit的容器的各层原始层叠加容器运行后的层所得,既n+1
2. save后load
就是原始镜像的各层,既n
3. export后import
将容器的系统文件作为一层放入镜像,既1
八. 基于容器制作新镜像
1. 基于centos6.9的镜像制作centos6.9+sshd+LAMP+PHP的镜像
(1). 运行基础centos6.9镜像
[root@andy centos]# mkdir -p /opt/vol/mysql /opt/vol/html
[root@andy centos]# docker run -it --name=old -v /opt/vol/mysql:/var/lib/mysql -v /opt/vol/html/:/var/www/html centos:6.9
(2). 安装需要的软件
# yum install openssl-server httpd mysql mysql-server php php-mysql -y
(3). 初始化刚安装的软件
3.1 sshd初始化
# /etc/init.d/sshd start
# /etc/init.d/sshd stop
3.2 mysqld初始化
# /etc/init.d/mysqld start
mysql> grant all on *.* to root@'%' identified by '123';
Query OK, 0 rows affected (0.00 sec)
mysql> grant all on *.* to discuz@'%' identified by '123';
Query OK, 0 rows affected (0.00 sec)
mysql> create database discuz charset utf8;
Query OK, 1 row affected (0.00 sec)
3.3 apache初始化
# /etc/init.d/httpd start
(4). 制作LAMP第一版基础镜像
# docker commit 3a57970e6767 centos_lamp:v1
(5). 根据第一版制作的镜像启动一个新容器
# docker container run -it --name old_v1 -v /opt/vol/mysql:/var/lib/mysql -v /opt/vol/html:/var/www/html -p 8080:80 centos_lamp:v1
[root@3fc96d397845 /]# /etc/init.d/mysqld start
[root@3fc96d397845 /]# /etc/init.d/httpd start
(6). 测试php功能
# vi /var/www/html/index.php
<?php
phpinfo();
?>
(7). 安装bbs论坛
上传bbs代码到宿主机/opt/vol/html目录
(8). 制作LAMP+BBS第二版镜像
# docker commit old_v1 centos_lamp:v2
(9). 创建容器启动的脚步
[root@andy centos]# cd /opt/vol/html/
[root@andy html]# vi init.sh
[root@andy html]# chmod 777 /opt/vol/html/init.sh
(10). 启动容器,映射端口,挂载数据卷,自启动多个服务
[root@andy html]# docker container run -d --name=new -v /opt/vol/mysql/:/var/lib/mysql -v /opt/vol/html/:/var/www/html -p 22222:22 -p 8888:80 -p 33060:3306 centos_lamp:v2 /var/www/html/init.sh
2. 基于centos7的容器做centos+sshd的镜像
(1). 下载并运行基础镜像centos7
# docker run -it --name=centos7base centos:7
(2).安装sshd服务
# yum install openssh-server -y
(3).初始化sshd
# mkdir /var/run/sshd
# echo 'UseDNS no' >> /etc/ssh/sshd_config
# sed -i -e '/pam_loginuid.so/d' /etc/pam.d/sshd
# echo 'root:123456' | chpasswd
# /usr/bin/ssh-keygen -A
(4).制作镜像
# docker commit e4b1b2f395ca centos7sshd:v1
(5).启动镜像
# docker container run -d -p 222:22 centos7sshd:v1 /usr/sbin/sshd -D
九. 用dockerfile制作镜像
1. FROM 基础镜像
FROM 镜像名:tag
FROM 镜像名@id
2. RUN 制作镜像过程中使用的命令
# 这种方法会自动加一个/bin/bash, 第一进程就是bash
RUN /etc/init.d/sshd start && /etc/init.d/sshd stop
# 这种方式不会加bash,第一进程就是mysqld
RUN ["mysqld","--initialztion-insecure","--user=mysql"]
3. ARG 定义在build镜像时使用的变量
在Dockerfile中使用,仅仅在build docker image的过程中(包括CMD和ENTRYPOINT)有效,在image被创建和container启动之后,无效。
如果你在Dockerfile中使用了ARG但并未给定初始值,则在运行docker build的时候未指定该ARG变量,则会失败。
虽然其在container启动后不再生效,但是使用‘docker history’可以查看到。所以,敏感数据不建议使用ARG.
4. ENV 定义在build镜像时使用的变量并且在容器启动后会作为环境变量
在Dockerfile中使用,在build docker imag的过程中有效,在image被创建和container启动后作为环境变量依旧也有效,并且可以重写覆盖。printenv可查看其值。
# Set ENV
ENV JMETER_HOME /jmeter/apache-jmeter-$JMETER_VERSION/
ENV PATH $JMETER_HOME/bin:$PATH
3. EXPOSE 暴露端口
EXPOSE 22
4. 从宿主机向镜像copy文件
ADD:如果要复制的是.tar*格式的压缩文件,会自动解压到镜像
COPY:不会自动解压
#两者都能把源文件用一个url地址,这样相当于wget一个文件到镜像
#如果复制的是目录,会把目录下文件和目录复制,不会复制目录本身
5. VOLUME匿名挂载镜像目录到宿主机目录
VOLUME[目录1,目录2...]
#当该镜像被run为一个容器时会自动创建在VOLUME后面列表中的所有目录,并且将这些目录匿名挂载到宿主机的某目录
6. ENV设定变量,这些变量在构建镜像和运行为一个容器后都存在
ENV 变量名 变量值
如:
ENV datadir /var/www/html
3. CMD 用镜像启动容器时运行的第一个命令(如果写多个CMD,之前的将被覆盖)
CMD ["/usr/sbin/sshd","-D"]
在run一个容器时执行的第一个命令
CMD的命令可以被run容器时指定的命令替换
4. ENTRYPOINT用镜像启动容器时运行的第一个命令(如果写多个entrypiont,不会覆盖,会都执行)
# ENTRYPOINT还要一个用法:后一个entrypoint的内容会作为前一个entrypoint内容的参数来执行
# entrypoint不能被run容器时手动指定的命令替换
十 制作私有registry仓库
1. 私有registry仓库需要运行在registry这个容器中,所以要下载并运行这个容器;5000端口是registry提供服务的端口需要把5000这个端口映射出来;/var/lib/registry这个目录是registry存放镜像的目录,需要把这个目录数据卷到宿主机上的目录
[root@andy ~]# docker run -d -p 5000:5000 --restart=always --name registry -v /opt/registry:/var/lib/registry registry
2. 修改registry容器宿主机的配置文件,并重启docker服务
[root@andy ~]# vi /etc/docker/daemon.json
{
"registry-mirrors":["https://68rmyzg7.mirror.aliyuncs.com"],
"insecure-registries":["192.168.1.223:5000"]
}
[root@andy ~]# systemctl restart docker
3.修改本地要上传到registry的镜像的镜像名为ip:端口号/名称:tag
[root@andy ~]# docker tag vinsdocker/jmserver 192.168.1.223:5000/jmeterserver:v1
4. 推送刚刚改为名的镜像到registry
[root@andy ~]# docker image push 192.168.1.223:5000/jmeterserver:v1
The push refers to a repository [192.168.1.223:5000/jmeterserver]
14ced7718937: Pushed
22616b527a01: Pushed
ead975661dc4: Pushed
96e700309364: Pushed
bca5421261df: Pushed
473adefcdec2: Pushed
7f877179d500: Pushed
9c0da68f893b: Pushed
e01103f88b34: Pushed
2ec5c0a4cb57: Pushed
v1: digest: sha256:1d261b04883e12d0d8ae728fc13e61efd334d353ff3cad325d1f961972d48c37 size: 2418
5. 查看本地库中的镜像文件
1 查看本地仓库容器中镜像的存放位置
[root@andy ~]# docker container inspect 9378451f8ffc | grep -i "source"
"Source": "/opt/registry",
2 进入这个目录查看镜像的文件
[root@andy ~]# cd /opt/registry/docker/registry/v2/repositories/
[root@andy repositories]# ls
jmeterserver
6. 在另一个机器上下载私有库中的镜像
- 修改daemon.json文件
[root@andy ~]# vi /etc/docker/daemon.json
{
"registry-mirrors":["https://68rmyzg7.mirror.aliyuncs.com"],
"insecure-registries":["192.168.1.223:5000"]
}
- pull镜像
[root@andy ~]# docker pull 192.168.1.223:5000/jmeterserver:v1
十一 给本地仓库加安全认证
1. 生成密码
# yum install httpd-tools -y
# mkdir /opt/registry-auth/ -p
# htpasswd -Bbn andy admin@123 > /opt/registry-auth/htpasswd
2. 运行带秘钥功能的registry容器
[root@andy ~]# docker run -d -p 5000:5000 -v /opt/registry-auth/:/auth/ -v /opt/registry:/var/lib/registry --name register-auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" registry
3. push镜像
1. 登录
[root@andy ~]# docker login 192.168.1.223:5000
Username: andy
Password:
Login Succeeded
4. 在另一台pc上先登录在pull私有库中镜像
[root@andy ~]# docker login 192.168.1.223:5000
Username: andy
Password:
Login Succeeded
You have mail in /var/spool/mail/root
[root@andy ~]# docker pull 192.168.1.223:5000/jmeterserver:v1
十二 发布镜像到docker hub
1. 注册一个hub账号,https://hub.docker.com/
2. 在docker hub上新建一个仓库
3. 向docker hub推送镜像
# 1. 从本地的container中找一个容器,commit为一个名为51clearsight/jmeter的新镜像
[root@andy ~]# docker container ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0b5773599fb5 mysql "docker-entrypoint..." 5 days ago Exited (1) 5 days ago nervous_mayer
3be04a772429 mysql "docker-entrypoint..." 5 days ago Exited (1) 5 days ago optimistic_joliot
77ecedd7afbb centos "/bin/bash" 5 days ago Up 5 days amazing_boyd
b1d35daa2f17 centos "/bin/bash" 5 days ago Exited (0) 5 days ago gracious_lewin
[root@andy ~]# docker commit b1d35daa2f17 51clearsight/jmeter
sha256:ca732998bb9f58f00dcdc21125c41ab8c740301182b72ac5e9139a52dbf6addd
# 2. 登录docker hub
[root@andy ~]# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: 51clearsight
Password:
Login Succeeded
# 3. push这个新镜像
[root@andy ~]# docker push 51clearsight/jmeter:latest
The push refers to a repository [docker.io/51clearsight/jmeter]
184916df9627: Pushed
291f6e44771a: Pushed
latest: digest: sha256:d0adb1c8046b8e5aacde1d245f91deaa2a06937d790d6f448dfd467c83035446 size: 736
4. 去docker hub查看push是否成功,如果成功应该看到tag有内容
十三 发布镜像到阿里云
1. 在阿里云上新建一个仓库
https://cr.console.aliyun.com/
2. 查看私有仓库的详情
3. 登录阿里云docker registry
[root@andy ~]# sudo docker login --username=clearsight51 registry.cn-beijing.aliyuncs.com
Password:
Login Succeeded
4. 将准备上传到阿里云的本地镜像tag重命名一下
docker tag ca732998bb9f registry.cn-beijing.aliyuncs.com/51tangseng/51clearsight:v1
5. 将重命名的镜像推送到Registry
[root@andy ~]# docker image push registry.cn-beijing.aliyuncs.com/51tangseng/51clearsight:v1
The push refers to a repository [registry.cn-beijing.aliyuncs.com/51tangseng/51clearsight]
184916df9627: Pushed
291f6e44771a: Pushed
v1: digest: sha256:d0adb1c8046b8e5aacde1d245f91deaa2a06937d790d6f448dfd467c83035446 size: 736
6. 从阿里云查看上传的镜像
7. 从另一台docker宿主机中下载刚刚上传的镜像
# 如果是公开镜像,不用登录,直接pull
docker pull registry.cn-beijing.aliyuncs.com/51tangseng/51clearsight:v1
十四 网络
1. 本地网络
1. 1 查看支持的网络类型
docker network ls
1.2. run容器时指定网络类型
docker run --network=xxx
1.3. 四种本地网络类型
bridge:默认模式,相当于NAT
host:所有容器共用宿主机的Network Namespace,即所有容器的机器名都是宿主机的机器名;所有容器的ip都是宿主机的ip;宿主机和各个容器的端口号不能重复,如果重复宿主机的优先,先开的容器端口号能用,后开的容器相同端口号不能用
container: 各个容器之间共用Network Namespace
none:无网络模式
1.4. bridge
1.4.1 bridge的特点
docker run -it -d --network=bridge centos6.9
默认run一个容器时网络类型就是bridge
特点:
# 宿主机可以ping通容器172.17.x.x
# 容器可以ping通宿主机的网络网卡地址
# 容器可以ping通所有外部设备
# 外部设备只能通过容器与宿主机的端口映射出的端口来访问容器的某些端口
# 容器间可以用ip或容器id来ping通;但无法提供容器名来ping;如果想要用容器名来互通在run一个容器时要加--link参数,如:
[root@andy ~]# docker run -id --name busybox3 --link busybox1 busybox
这个参数的作用是在新run的容器busybox3中的host文件中加入172.17.0.X busybox1
1.4.2. 创建自定义的bridge类型网络(自定义的brdge网络的各个容器间可以用容器名来互相访问)
1.
[root@andy ~]# docker network create --subnet 192.168.20.0/24 --gateway 192.168.20.1 -o parent=ens160 mybr0
a5626b4a59ef1e875404e1a3d744403aa94568a797688848dfefa1528d9d3328
2.
[root@andy ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
82b558fe2ebf bridge bridge local
b91c40f698d8 host host local
a5626b4a59ef mybr0 bridge local
58533a68f0a2 none null local
3.
[root@andy ~]# docker network inspect mybr0
[
{
"Name": "mybr0",
"Id": "a5626b4a59ef1e875404e1a3d744403aa94568a797688848dfefa1528d9d3328",
"Created": "2020-09-10T01:04:44.377764788+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.20.0/24",
"Gateway": "192.168.20.1"
}
]
},
"Internal": false,
"Attachable": false,
"Containers": {},
"Options": {
"parent": "ens160"
},
"Labels": {}
}
]
4.
[root@andy ~]# docker run -id --name mybox1 --network mybr0 busybox
ccee428c31e58a41c21deea90e57075d97b71d8bed9720090cf9d8fc6e93f305
[root@andy ~]# docker run -id --name mybox2 --network mybr0 busybox
d832666b036dbf441c52c722dc228926a34a3785a1dce308f6fdd0b949e5327d
[root@andy ~]# docker exec -it mybox1 ping mybox2
PING mybox2 (192.168.20.3): 56 data bytes
64 bytes from 192.168.20.3: seq=0 ttl=64 time=0.114 ms
64 bytes from 192.168.20.3: seq=1 ttl=64 time=0.117 ms
1.4.3 不同bridge上的容器互通(本质是让某个容器有两块网卡)
1. 用network connect命令把busybox1这个容器连接到桥mybr0上
[root@andy ~]# docker network connect mybr0 busybox1
2. 查看容器busybox1有两个网络bridge和mybr0
[root@andy ~]# docker container inspect busybox1
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "ebcf64e21dc8ab970b820d92003fcd60dbba5d339bcfdb6455bca6d719ac7682",
"EndpointID": "47f76d7f585056d34c419293279ecb236e978b04a60fde6259fcbc032ff28fba",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:03"
},
"mybr0": {
"IPAMConfig": {},
"Links": null,
"Aliases": [
"ff37925f147c"
],
"NetworkID": "a5626b4a59ef1e875404e1a3d744403aa94568a797688848dfefa1528d9d3328",
"EndpointID": "47f567526511687dcd60858004ad6cc70b26cab806f61c4422510b9391ad56ff",
"Gateway": "192.168.20.1",
"IPAddress": "192.168.20.4",
"IPPrefixLen": 24,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:c0:a8:14:04"
}
3. 用容器busybox1 连通 桥mybr0上的容器,是可以ping通的
[root@andy ~]# docker exec -it busybox1 ping 192.168.20.3
PING 192.168.20.3 (192.168.20.3): 56 data bytes
64 bytes from 192.168.20.3: seq=0 ttl=64 time=0.152 ms
64 bytes from 192.168.20.3: seq=1 ttl=64 time=0.099 ms
1.5. container
- container类型的网络是多个容器之间使用同一个namespace
- 使用方法:
# 创建一个httpd容器使用默认bridge网络
[root@andy ~]# docker run -itd --name web1 httpd
# 再创建一个busybox容器,让他使用container类型的网络并且指定和容器web1共用namespace
[root@andy ~]# docker run -itd --network container:web1 --name busy busybox
- 用处:
当两个容器要通过loopback口快速通信时;
当一个容器要监控另一个容器的网卡时
2. 跨主机网络(让不同docker宿主机里的容器能够互通)
2.1 两种跨主机网络类型
macvlan:
2.2 macvlan
- macvlan技术
macvlan是一种linux虚拟网络设备技术,准确的说是网卡虚拟化技术,即把一块网络网卡虚拟成多块虚拟网卡 - macvlan的工作原理
macvlan 是 Linux kernel 支持的新特性,支持的版本有 v3.9-3.19 和 4.0+,比较稳定的版本推荐 4.0+。它一般是以内核模块的形式存在,我们可以通过以下方法判断当前系统是否支持:
如果第一个命令报错,或者第二个命令没有返回,说明当前系统不支持 macvlan,需要升级内核。
macvlan 这种技术听起来有点像 VLAN,但它们的实现机制是完全不一样的。macvlan 子接口和原来的主接口是完全独立的,可以单独配置 MAC 地址和 IP 地址,而 VLAN 子接口和主接口共用相同的 MAC 地址。VLAN 用来划分广播域,而 macvlan 共享同一个广播域。
通过不同的子接口,macvlan 也能做到流量的隔离。macvlan 会根据收到包的目的 MAC 地址判断这个包需要交给哪个虚拟网卡,虚拟网卡再把包交给上层的协议栈处理。
3. 四种模式
根据 macvlan 子接口之间的通信模式,macvlan 有四种网络模式:
private 模式
vepa(virtual ethernet port aggregator) 模式
bridge 模式
passthru 模式
- macvlan用于docker网络
4.1 docker的macvlan只支持bridge模式
4.2 跨主机的容器使用相同macvlan进行通信的步骤:
1. 使用docker network create命令分别在所有docker宿主机上创建macvlan网络
[root@slave03 dockerfile]# docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 -o parent=ens160 andy
be7b9af7c13906671dad3cc9cf5659f34e46ce84f4c60168f7370595d8a981a9
-d 指定 Docker 网络 driver
--subnet 指定 macvlan 网络所在的网络
--gateway 指定网关
-o parent 指定用来分配 macvlan 网络的物理网卡
最后那个andy是随便起的一个macvlan名
2. 查看主机的网络环境,其中应该出现了 macvlan 网络
[root@slave03 dockerfile]# docker network ls
NETWORK ID NAME DRIVER SCOPE
be7b9af7c139 andy macvlan local
5cc154dc801b bridge bridge local
b91c40f698d8 host host local
58533a68f0a2 none null local
3. 在第一台docker宿主机192.168.1.226上运行一个名叫macvlan1的容器并指定使用macvlan网络
docker run -itd --name macvlan1 --ip=192.168.1.236 --network andy busybox
这条命令中,
--ip 指定容器 macvlan1 使用的 IP,这样做的目的是防止自动分配,造成 IP 冲突
--network 指定 macvlan 网络
4. 同样在第二台docker宿主机192.168.1.227上运行一个名叫macvlan2的容器并指定使用macvlan网络
docker run -itd --name macvlan2 --ip=192.168.1.237 --network andy busybox
4.3 跨主机的容器使用不同macvlan进行通信的步骤(二层无法通信,需要借助三层路由):
安装上图分别在宿主机192.168.1.226和192.168.1.227上配置docker
192.168.1.226
docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 -o parent=ens160 andy
docker network create -d macvlan --subnet=192.168.11.0/24 --gateway=192.168.11.1 -o parent=ens160 tom
十五 docker图形化界面管理工具之portainer
1. 启动portainer容器
[root@andy ~]# docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true --name keshihua portainer/portainer
[root@andy ~]# docker port keshihua
9000/tcp -> 0.0.0.0:8088
2. 登录portainer web界面
十五 docker服务端开启端口提供外部访问
15.1 服务端开启端口的操作步骤
-
编辑daemon.json文件,加入以下内容
-
reload配置并重启docker
3. 查看2375端口启动成功
15.2 在其他docker机器上用docker -H ip地址来访问
十五 镜像的分层结构
15.1 分层结构
- 容器使用宿主机的bootfs Kernel
- 不同的操作系统镜像在镜像最底层有各自的rootfs即目录结构
- 镜像各层的冷数据无法修改
- 容器中的热数据在容器关闭后丢失
15.2 容器中数据的读取和处理
- 容器读取数据时如果有几个镜像层都有该数据,会读取上层镜像层的数据
- 容器层对读取到容器层的数据的删,改,增都不会影响镜像层数据
十六 docker machine
16.1 docker machine的作用
在一台docker宿主机上通过安装docker machine来使他能操控其他linux主机来安装docker并操作其上的docker
16.2 安装docker machine
- 从https://github.com/docker/machine/releases/download 下载docker machine
curl -L https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine
或者自动安装:
base=https://github.com/docker/machine/releases/download/v0.16.1 &&
curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine &&
sudo install /tmp/docker-machine /usr/local/bin/docker-machine
2. 给下载的文件添加可执行权限
3. 将下载的程序放到/usr/local/bin目录下
4. 验证docker machine安装成功
16.3 下载bash completion scripts
-
bash completion scripts提供了在shell提示符中显示活动计算机名,使用子命令来切换活动机器等功能
-
确认docker machine的版本,并下载相应版本的脚本(docker-machine-prompt.bash 和 docker-machine-wrapper.bash 和 docker-machine.bash)到/etc/bash_completion.d 或 /usr/local/etc/bash_completion.d
下载这三个脚本的命令如下:
base=https://raw.githubusercontent.com/docker/machine/v0.16.0
for i in docker-machine-prompt.bash docker-machine-wrapper.bash docker-machine.bash
do
sudo wget "$base/contrib/completion/bash/${i}" -P /etc/bash_completion.d
done
或者离线安装:
从https://github.com/docker/machine/tree/v0.16.1/contrib/completion/bash(对应版本号)下载以下三个脚本文件,然后拷贝到/etc/bash_completion.d目录下。
docker-machine-prompt.bash
docker-machine-wrapper.bash
docker-machine.bash
16.4 加载docker-machine-prompt.bash
16.5 启用docker-machine的shell提示
添加 $(__docker_machine_ps1)到PS1设置中~/.bashrc
vim ~/.bashrc,添加以下内容。
PS1='[\u@\h \W$(__docker_machine_ps1)]\$ '
16.6 安装docker-machine的服务器要控制其他linux的docker安装需要配置免密ssh访问这台linux
配置免密登录步骤:
192.168.1.223安装了docker-machine,需要配置免密登录192.168.1.228来操控docker
-
在223上生成自己的一对公、私钥
ssh-keygen -t rsa
-
把自己的公钥给228的root用户
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.228
-
免秘钥登录
-
免秘钥登录原理
16.7 在linux主机上安装docker
- 创建docker host(在主机上安装docker)
docker-machine create --driver generic --generic-ip-address=192.168.1.228 andy1
- 查看docker client
16.8 查看machine的环境变量
- 查看docker client andy1的环境变量
- 操作andy1
十七 docker 的监控
17.1 docker container top 容器名
用来查看一个容器中的进程
17.2 docker container stats
查看宿主机中所有容器的cpu,内存,网络使用情况
17.3 sysdig
- 下载sysdig镜像
[root@andy1 ~]# docker pull sysdig/sysdig
- 运行sysdig容器
[root@andy1 ~]# docker container run -it --name sysdig --privileged=true --volume=/var/run/docker.sock:/host/var/run/docker.sock --volume=/dev:/host/dev --volume=/proc:/host/proc:ro --volume=/boot:/host/boot:ro --volume=/lib/modules:/host/lib/modules:ro --volume=/usr:/host/usr:ro sysdig/sysdig
- 进入容器并执行csysdig来监控
docker container exec -it sysdig bash
17.4 Cadvisor
我们可以使用多种方法监控容器的运行情况,比如EFK等,但是我们仍旧需要一个资源利用率监控系统。这个时候,google开发的cadvisor就可以帮上我们的忙了。
- 安装Cadvisor
[root@andy1 ~]# docker run --volume=/:/rootfs:ro --volume=/var/run:/var/run:rw --volume=/sys:/sys:ro --volume=/var/lib/docker/:/var/lib/docker:ro --publish=8089:8080 --detach=true --name=cadvisor google/cadvisor:latest
- 使用
十八 Compose
18.1 安装
[root@andy1 ~]# curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
[root@andy1 ~]# chmod +x /usr/local/bin/docker-compose
[root@andy1 ~]# docker-compose --version
docker-compose version 1.26.2, build eefe0d31
18.2 基本操作流程
- 建立项目目录
- 向目录中放入app.py和requirements.txt
- 建立Dockerfile
- 建立compose file并在里面定义服务
- 在项目目录中用命令docker-compose up建立并运行各个服务
18.3 docker-compse基本命令
-
docker-compose up 建立并运行compose文件中定义的所有服务
-
docker-compose up -d建立并后台运行各个服务
-
docker-compose up web 只建立和运行compose文件中服务名为web的服务
-
用命令docker-compose down停止各个服务并删除容器
-
用命令CTRL+C停止各个服务,但不删除容器
-
用命令docker-compose stop停止各个服务,但不删除容器
-
用命令docker-compose down --volumes停止各个服务并删除容器并删除数据卷
-
登录到已经运行的服务中并执行命令
登录到web服务,并运行命令python
docker-compose exec web python
18.4 compose file-docker-compose.yaml
- compose file有三层:版本;服务;其他配置
- compose文件中的version要和docker 引擎的版本匹配
- build
用Dockerfile文件来build一个镜像,并run成一个容器
build # 指定包含构建上下文的路径, 或作为一个对象,该对象具有 context 和指定的 dockerfile 文件以及 args 参数值
context # context: 指定 Dockerfile 文件所在的路径
dockerfile # dockerfile: 指定 context 指定的目录下面的 Dockerfile 的名称(默认为 Dockerfile)
args # args: Dockerfile 在 build 过程中需要的参数 (等同于 docker container build --build-arg 的作用)
cache_from # v3.2中新增的参数, 指定缓存的镜像列表 (等同于 docker container build --cache_from 的作用)
labels # v3.3中新增的参数, 设置镜像的元数据 (等同于 docker container build --labels 的作用)
shm_size # v3.5中新增的参数, 设置容器 /dev/shm 分区的大小 (等同于 docker container build --shm-size 的作用)
dockerfile为/root/test123
dockerfile在compose项目目录下并且文件名为Dockerfile
dockerfile是当前目录下的dir目录中的Dockerfile-alternate
build参数中的args参数是定义build时使用的环境变量的,有两种方式定义:mapping和list
build参数中的network参数是定义在build镜像时dockerfile文件中RUN命令运行时用的网络
- command
command # 覆盖容器启动后默认执行的命令, 支持 shell 格式和 [] 格式
- container_name
container_name # 指定容器的名称 (等同于 docker run --name 的作用)
- depends_on
depends_on # 定义容器启动顺序 (此选项解决了容器之间的依赖关系, 此选项在 v3 版本中 使用 swarm 部署时将忽略该选项)
示例:
docker-compose up 以依赖顺序启动服务,下面例子中 redis 和 db 服务在 web 启动前启动
默认情况下使用 docker-compose up web 这样的方式启动 web 服务时,也会启动 redis 和 db 两个服务,因为在配置文件中定义了依赖关系
version: '3'
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
- networks
将容器加入指定网络 (等同于 docker network connect 的作用), networks 可以位于 compose 文件顶级键和 services 键的二级键
- volumes
volumes # 定义容器和宿主机的卷映射关系, 其和 networks 一样可以位于 services 键的二级键和 compose 顶级键, 如果需要跨服务间使用则在顶级键定义, 在 services 中引用
SHORT 语法格式示例:
volumes:
- /var/lib/mysql # 映射容器内的 /var/lib/mysql 到宿主机的一个随机目录中
- /opt/data:/var/lib/mysql # 映射容器内的 /var/lib/mysql 到宿主机的 /opt/data
- ./cache:/tmp/cache # 映射容器内的 /var/lib/mysql 到宿主机 compose 文件所在的位置
- ~/configs:/etc/configs/:ro # 映射容器宿主机的目录到容器中去, 权限只读
- datavolume:/var/lib/mysql # datavolume 为 volumes 顶级键定义的目录, 在此处直接调用
LONG 语法格式示例:(v3.2 新增的语法格式)
version: "3.2"
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- type: volume # mount 的类型, 必须是 bind、volume 或 tmpfs
source: mydata # 宿主机目录
target: /data # 容器目录
volume: # 配置额外的选项, 其 key 必须和 type 的值相同
nocopy: true # volume 额外的选项, 在创建卷时禁用从容器复制数据
- type: bind # volume 模式只指定容器路径即可, 宿主机路径随机生成; bind 需要指定容器和数据机的映射路径
source: ./static
target: /opt/app/static
read_only: true # 设置文件系统为只读文件系统
volumes:
mydata: # 定义在 volume, 可在所有服务中调用
18.5 compse中设置环境变量
-
使用shell中的环境变量
用${变量名}
-
把环境变量的定义都写到项目目录下的.env文件中,会被自动读取
- 用–env-file参数指定其他任意目录下的任意文件名的环境变量文件