Docker:基础篇

摘要

docker 主要有两个部分进行组成,一个是镜像(第二节),一个容器(第三节)。下面将介绍,镜像的常用操作与容器的常用的操作。
有两个问题:1、容器之间的数据通信(第四节)。2、容器之间的数据共享(第五节)。这两个问题在下面也将展开介绍。

一、什么是Docker及其体系架构

1、什么是Docker?体系架构

(1)Docker是一个容器的引擎(虚拟机)
(2)让开发人员可以打包自己的应用程序(依赖:包、资源)
(3)虚拟化
(4)组成:

  • Docker Client客户端:Docker命令
  • Docker Daemon守护进程
  • Docker Image镜像模板:分层结构
  • Docker Container容器
    在这里插入图片描述
    docker就是一个管理员,管理其内部的容器,而每个容器可以看做一个服务,那么,如何把服务装配在容器之中,是通过镜像进行创建,就可以把服务装进容器之中,进而提供服务。那么,可能会产生两个问题:1、容器之间是如何进行通信。2、容器之间如何进行数据共享。这两个问题在下面都会提到。

2、安装和配置Docker实验环境:Ubuntu 16.04

Ubuntu进行安装docker

apt-get install docker.io
启动Docker服务
systemctl start docker
systemctl enable docker 开机自启
查看Docker版本
docker version

二、Docker的镜像:image(模板---->创建容器)

什么是Docker镜像?
(1)镜像是一个模板
(2)镜像采用分层的文件系统
(3)镜像是容器运行的基石
(4)可以从镜像仓库中进行拉取(公有、私有harbor)

0、持久化镜像

Save命令用于持久化镜像(不是容器)。所以,我们就需要通过以下方法得到镜像名称:
   sudo docker images
接着执行保存:
   sudo docker save busybox-1 > /home/save.tar
加载命令 docker load --input ***.tar

0.0 持久化容器

Export命令用于持久化容器(不是镜像)。所以,我们就需要通过以下方法得到容器ID:
   sudo docker ps -a
接着执行导出:
   sudo docker export <CONTAINER ID> > /home/export.tar
加载命令
  docker	import  **.tar  name:version

0.0.0 修改镜像名字和TAG

docker tag 1417b43a3ff5 faster-rcnn-3d:v1

1、使用和访问官方的Docker的镜像仓库(hub) https://hub.docker.com

常用命令:

docker search **** 搜索镜像模板
docker pull *** 拉取镜像(下载本地)
docker run 命令创建容器
docker ps  查看正在运行的容器

举例1:拉取MySQL的镜像,创建一个容器

docker search mysql
docker pull mysql  ----> 默认:latest版本
docker images  ----> 查看本地下载的镜像
docker run --name my_mysql_demo -p 3306:3306 -e MYSQL_ROOT_PASSWORD=Welcome_1 -d mysql

说明:        
--name 指定容器的名称
-p     指定宿主机和容器之间的端口映射
-e     设置环境变量
-d     启动容器进程(后台,返回container id)
mysql  镜像的名称

进入容器:

docker exec -it CONTAINER_ID /bin/bash
docker exec -it eadee3a87f29 /bin/bash

2、配置和使用阿里云提供的Docker镜像加速器

阿里云官方配置
Ubuntu,其他点击上方链接

1. 安装/升级Docker客户端
推荐安装1.10.0以上版本的Docker客户端,参考文档 docker-ce

2. 配置镜像加速器
针对Docker客户端版本大于 1.10.0 的用户

您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://7s1e9gp7.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

加速地址:https://7s1e9gp7.mirror.aliyuncs.com

3、管理镜像(Docker命令)

docker search [NAME] 在镜像仓库中搜索镜像
docker pull [NAME] 拉取镜像(latest)
docker push [NAME] 上传到镜像仓库中
docker images 列出本地的所有镜像(基本信息)
docker images m*  支持通配符
docker inspect [NAME]/[CONTAINER_ID] 列出镜像(容器)的详细信息
docker rmi [NAME] 删除镜像
		                参数:-f 强制删除
						如果有多个镜像,采用空格进行分隔
docker run 使用镜像创建容器

4、构建Docker镜像(上传到docker hub)

(1)使用docker commit
举例:
1、使用Docker部署一个Tomcat的容器

docker pull tomcat
docker run -d --name tomcat_web_app -p 8080:8080 tomcat

2、在Tomcat容器中部署一个简单的Web应用(修改容器)

docker exec -it 6490798df72b /bin/bash					
cd webapps
mkdir mydemo
cd mydemo
echo '<h1>Hello Tomcat</h1>' > a.html

3、将容器保存docker commit -----> 本地

docker commit 6490798df72b tomcat_web_app_local

将容器保存docker commit -----> 镜像仓库中
登录 docker login,首先在https://hub.docker.com 进行创造用户。
注意 :collenzhao/tomcat_web_app_remote ,创建这个名字必须和自己创建的仓库保持一致,并且‘/’前必须指定自己的用户名。

docker commit 6490798df72b collenzhao/tomcat_web_app_remote

4、使用docker push命令上传的镜像

docker push collenzhao/tomcat_web_app_remote

(2)使用Dockerfile(命令:docker build)
Dockerfile就是根据自己的需求构建本地镜像
1、创建一个Dockerfile(-f参数指定文件名称)
基于Nginx镜像,部署一个简单的Web App应用

FROM nginx
RUN echo '<h1>This is a Demo WebApp</h1>' > /usr/share/nginx/html/index.html

2、使用docker build命令,生成镜像

docker build -t nginx:mylatest .
-f  : 指定dockerfile文件名
-t : 指定生成镜像的名字
: :指标签、备注
. : 意思是把构成的最后的镜像保本到本地

3、创建一个容器

docker run -d -p 7788:80 nginx:mylatest 

5、Dockerfile使用(综合例子)

(1)Docker镜像、Docker容器、Dockerfile三者的关系
在这里插入图片描述
实际上dockerfile就是构建一个新的镜像,dockerfile里的每一条指令都会生成一个新的镜像,并且输出最后生成的哪个镜像。

(2)Dockerfile的基本概念

  • Docker镜像是一个特殊的文件系统
  • Dockerfile基于文本的配置文件,包含一条条的指令。每一条指令构建分层文件系统中的一层
  • docker build构建image镜像

(3)Dockerfile文件格式:4部分

  • 基础镜像信息
  • 维护者的信息,miantainer
  • 镜像操作命令
  • 容器启动执行的命令,cmd 、entrypoint
    在这里插入图片描述
    FROM 指定基础镜像
    MAINTAINER 维护者的信息
    RUN 执行一条命令
    COPY 从宿主机上拷贝一个文件到镜像模板中
    ENV 设置环境变量
    ADD 添加一个URL的地址(下载文件)
    ENTRYPOINT 启动容器的时候,执行命令

CMD与ENTRYPOINT的区别

  1. ENTRYPOINT指令
    执行docker run如果带有其他命令参数,不会覆盖ENTRYPOINT指令。
    ENTRYPOINT [“top”,"-b", “-H”]
    exec格式,也被称为JSON风格[“command”,“arg1”]。
    在创建容器实例执行docker run命令时,设置的任何命令参数,都将作为ENTRYPOINT指令的命令参数,追加到ENTRYPOINT指令的命令之后。

  2. CMD指令
    执行docker run如果带有其他命令参数,将会覆盖CMD指令。

(4)综合的例子:

(#)从一个基本的centos基础镜像开始
(#)安装JDK和Tomcat
(#)在tomcat中部署一个Web App应用
(#)启动容器,访问Web App的应用
创建Dockerfile

FROM centos
MAINTAINER zhaoqiang zhaoqiang@example.com
RUN mkdir /root/training
RUN mkdir /root/tools
COPY jdk-8u144-linux-x64.tar.gz /root/tools
RUN tar zxvf /root/tools/jdk-8u144-linux-x64.tar.gz -C /root/training/
ENV JAVA_HOME /root/training/jdk1.8.0_144
ENV PATH $JAVA_HOME/bin:$PATH
ADD http://mirror.bit.edu.cn/apache/tomcat/tomcat-8/v8.5.35/bin/apache-tomcat-8.5.35.tar.gz /root/tools
RUN tar zxvf /root/tools/apache-tomcat-8.5.35.tar.gz -C /root/training/
COPY MyDemoWeb.war /root/training/apache-tomcat-8.5.35/webapps
ENTRYPOINT ["/root/training/apache-tomcat-8.5.35/bin/catalina.sh","run"]	

编译的命令:docker build -t mywebapp .
启动容器: docker run -d -p 8080:8080 mywebapp

三、Docker的容器(container)

1、容器的基本操作:创建容器、停止容器、进入容器、删除容器

(1)创建容器
命令:run、create、start
区别:run = create + start
例子:docker create --name mycontainer1 centos
无法通过docker ps命令来查看容器,因为容器没有运行
docker start [container id]

(2)停止容器 docker stop

(3)进入容器 docker exec -it 47ceba4e6e66 /bin/bash
参数 -i 保持标准输入打开 、 -t 分配一个伪终端

(4)删除容器: docker rm 47ceba4e6e66
docker rmi [镜像id] 是删除镜像,注意区分。

(5)导入和导出容器(迁移)
注意:不管容器处于什么状态,都可以使用export导出操作
docker export
docker export -o mywebapp.tar 47ceba4e6e66

docker import 把导入的tar包变成一个镜像
docker import mywebapp.tar mywebapp_imported

2、容器的日志

(1)Docker引擎的日志:一般来说,由操作系统来维护

Ubuntu16.04: journalctl -u docker.service

在这里插入图片描述
(2)容器的日志:命令 docker logs [CONTAINER_ID]
命令:docker logs -f -t --since=“2018-12-01” --tail=20 47ceba4e6e66

-f 查看实时日志,类似 tail -f
-t 查看日志产生的日期
--since 指定了输入日志的开始期(只输出指定日期后产生的日志)
--tail   查看最后的20条日志

3、管理容器的资源

(1)基础知识:Linux Control Groups

(-)什么是Linux Control Groups?
简单来说:以一组进程为目标进行系统资源的分配和控制。对资源的限制。
(-)功能

  • 限制资源的使用
  • 优先级的控制
  • 审计
  • 控制功能:挂起进程、恢复执行进程
    (-)查看Linux的内核中,是否启用了cgroup的功能
    uname -r
    cat /boot/config-4.4.0-142-generic |grep CGROUP
    在这里插入图片描述
    y代表yes
    (-)Demo1:限制进程(应用程序)对CPU的使用率
    开发一个c程序:死循环
int main(void){
		int i=0;
		for(;;) i++;
		return 0;
	}

使用gcc进行编译: yum install gcc
gcc -o hello hello.c
== 对应用程序的CPU的使用率进行限制:20% ==

cd /sys/fs/cgroup/cpu
mkdir my001
cd my001

查看cat cpu.cfs_quota_us
-1 表示:没有任何的限制

echo 20000 > cpu.cfs_quota_us
把hello的进程号 ---> tasks中
echo 6565 > tasks

再启动一个hello程序
两个hello程序总的CPU的使用:20%

(-)Demo2:限制进程(应用程序)对内存的使用
cd /sys/fs/cgroup/memory/my001 如果没有这个目录,创建这个目录
查看cat memory.limit_in_bytes
9223372036854771712 可以没有任何限制

规定hello的应用程序最多只能使用64K的内存
echo 64k > memory.limit_in_bytes
				
把hello的进程号写到tasks
echo 6633 > tasks

== 如果6633(hello的应用程序)的内存使用超过64K,自动被kill ==

(-)Demo3:限制进程(应用程序)对I/O使用
安装工具:iotop 类似top命令 监视磁盘的IO的情况
命令:dd if=/dev/sda of=/dev/null 不断访问磁盘
使用iotop监视磁盘的IO的情况

cd /sys/fs/cgroup/blkio/my001  如果没有这个目录,创建这个目录
显示对磁盘的IO的访问:10M之内
echo '8:0 10485760' > blkio.throttle.read_bps_device
把进程号输出到tasks中(生效)
echo 6671 > tasks

(2)Docker对容器使用CPU的使用率:是相对权重

准备实验的环境 Dockerfile

FROM centos:latest
RUN yum install -y epel-release && yum install -y stress
ENTRYPOINT ["stress"]

stress 启动压力测试

docker build -t centos001 .

启动两个容器,分配CPU使用率的不同权重(相对)

docker run -it centos001 --cpu 4     ----> 默认CPU使用率的权重:1024
docker run -it -c 512 centos001 --cpu 4  ----->CPU使用率的权重:512
注意:-c 512,必须卸载centos001之前,因为写在之后,会变成stress的参数。

通过命令:docker stats

CONTAINER           CPU %              
ecd45c19e72d        32.50%             
3562d2c5a40f        66.21%         

(3)Docker对容器使用的内存管理和限制

默认:一个容器可以使用宿主机上所有的内存
使用命令:docker run -m开关:使用内存的大小

docker run -it -m 128m centos001 --cpu 4
 -m 指定容器的使用内存的上限

通过docker stats查看

CONTAINER           CPU %               MEM USAGE / LIMIT  
1cb50eaff3f4        97.36%              192 KiB / 128 MiB  

(4)Docker对容器使用I/O的管理和限制

  • Demo1: --blkio-weight 参数(测试的时候,效果不是很理想)
docker run -it --blkio-weight 100 centos /bin/bash
docker run -it --blkio-weight 1000 centos /bin/bash

在两个容器中,同时执行dd命令
dd if=/dev/zero of=test.out bs=1M count=3000

  • Demo2:–device-read-bps和–device-write-bps
    限制容器读入和写出的速率:1M(每秒)
    写入速率的上限:1M
docker run -it --device-write-bps /dev/sda:1mb centos /bin/bash

在容器内部:dd if=/dev/zero of=test.out bs=1M count=20 oflag=direct
oflag=direct表示:读写数据采用直接IO
读取数据速率的上限:1M

docker run -it --device-read-bps /dev/sda:1mb centos /bin/bash
  • Demo3: --device-write-iops和–device-read-iops
    以写数据为例:容器write iops 是5/秒(次数)
docker run -it --device-write-iops /dev/sda:5 centos /bin/bash

在容器内部执行: dd if=/dev/zero of=test.out bs=1M count=200 oflag=direct
使用命令观察: iostat 1 (安装:yum install sysstat)
也能针对读,进行限制

docker run -it --device-read-iops /dev/sda:5 centos /bin/bash

四、Docker网络和容器的通信

在这里插入图片描述
docker的网络通信的实质就是虚拟的接口的隐射

1、Docker网络通信的基本原理

(1)Docker的网络接口是虚拟的接口
(2)虚拟的网络接口的转发的效率高
(3)宿主机的信息

docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
inet6 fe80::42:52ff:fe4b:4e4c  prefixlen 64  scopeid 0x20<link>
ether 02:42:52:4b:4e:4c  txqueuelen 0  (Ethernet)
RX packets 8  bytes 536 (536.0 B)
RX errors 0  dropped 0  overruns 0  frame 0
TX packets 8  bytes 648 (648.0 B)
TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
vethd1b406d: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
inet6 fe80::78da:cfff:feef:44b5  prefixlen 64  scopeid 0x20<link>
ether 7a:da:cf:ef:44:b5  txqueuelen 0  (Ethernet)
RX packets 8  bytes 648 (648.0 B)
RX errors 0  dropped 0  overruns 0  frame 0
TX packets 16  bytes 1296 (1.2 KiB)
TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

(4)到容器内部查看网卡的信息

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
inet 172.17.0.2  netmask 255.255.0.0  broadcast 0.0.0.0
inet6 fe80::42:acff:fe11:2  prefixlen 64  scopeid 0x20<link>
ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
RX packets 1819  bytes 8445579 (8.0 MiB)
RX errors 0  dropped 0  overruns 0  frame 0
TX packets 1687  bytes 95886 (93.6 KiB)
TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

(5)Docker创建容器的时候,会执行下面的操作

  • 创建一对的虚拟的网络接口,一个放在本地的主机和新容器的各自的命名空间中
  • 本地主机一端的虚拟的接口连接到默认的docker0的网桥上,取名:veth****
  • 容器一端:把虚拟的网络接口放到新容器中,改名:eth0
  • 从网桥(docker0)获取一个空闲的IP地址,分配给容器的eth0的网卡

2、Docker的网络模式:

四种不同的网络模式:host、container、bridge(默认)、none
命令:docker network ls

NETWORK ID          NAME                DRIVER              SCOPE
845b88ede2ca        bridge              bridge              local
74a262ef9181        host                host                local
6bcd1c1ff2ea        none                null                local

镜像:busybox集成了一百多个Linux的工具箱

(1)host:容器不会虚拟出自己的网卡,直接使用宿主机的IP和端口

docker run -it --network=host busybox /bin/sh

信息:

docker0   Link encap:Ethernet  HWaddr 02:42:52:4B:4E:4C  
 inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
  inet6 addr: fe80::42:52ff:fe4b:4e4c/64 Scope:Link
  UP BROADCAST MULTICAST  MTU:1500  Metric:1
  RX packets:1692 errors:0 dropped:0 overruns:0 frame:0
  TX packets:1812 errors:0 dropped:0 overruns:0 carrier:0
  collisions:0 txqueuelen:0 
  RX bytes:72456 (70.7 KiB)  TX bytes:8444973 (8.0 MiB)				

(2) container:容器不会虚拟出自己的网卡,和一个指定的容器共享IP和端口
启动两个容器:第一个 docker run -it busybox /bin/sh —> 使用bridge的模式
信息

eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
 inet addr:172.17.0.2  Bcast:0.0.0.0  Mask:255.255.0.0

第二个 docker run -it --network=container:d8c0a1aa2673 busybox /bin/sh 、 其中:d8c0a1aa2673是另一个容器的ID

eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
inet addr:172.17.0.2  Bcast:0.0.0.0  Mask:255.255.0.0

(3)bridge:默认的模式,会为每一个新创建的容器分配网络配置(IP等等)
(4)none:关闭了容器的网络功能

docker run -it --network=none busybox /bin/sh

通过ifconfig,无法查看到eth0的信息

(5) 自定义bridge的模式

  • 创建自己的网络:bridge
docker network create -d bridge --ip-range=192.168.78.0/24 --gateway=192.168.78.1 --subnet=192.168.78.0/24 bridge2

查看网络模式的详情:docker network inspect 3e7b5641cbeb

  • 创建自己的容器,使用自定义的网络模式(bridge2)
docker run -it --network=bridge2 --ip=192.168.78.3 busybox
docker run -it --network=bridge2 --ip=192.168.78.4 busybox

3、容器间的通信

可以通过IP进行访问,也可以通过name进行访问。
(1)IP通信

docker run -it --network=bridge2 --ip=192.168.78.3 busybox
docker run -it --network=bridge2 --ip=192.168.78.4 busybox	

缺点:不够灵活
(2)Docker DNS Server
参数:–name

docker run -it --network=bridge2 --name box1 busybox
docker run -it --network=bridge2 --name box2 busybox

(3)Joined容器:本质就是container网络模式
基于httpd的镜像创建容器

docker run -it --name box3 httpd

使用Joined容器创建一个新的容器

docker run -it --network=container:box3 busybox

测试:在第二个容器中执行wget 127.0.0.1

4、容器访问控制

(1)容器访问外部网络
需要宿主机的转发

docker run -it centos
sysctl net.ipv4.ip_forward ---> 是1,开启了转发功能
				                                是0,没有开启转发

通过下面方式开启
sysctl -w net.ipv4.ip_forward=1
更简单:启动docker服务的时候指定: --ip-forward=true

(2)外部访问容器网络:通过指定-p参数进行端口映射

docker run -it -p 80:80 centos bash
在宿主机上:iptables -nL查看

五、Docker的数据管理:数据的共享

1、Docker的数据卷(共享目录)

(1)相当于mount操作,mount:它可以将分区挂接到Linux的一个文件夹下,从而将分区和该目录联系起来,因此我们只要访问这个文件夹,就相当于访问该分区了。
(2)是一个可供容器使用的特殊的目录
(3)实现主机操作系统与容器之间进行目录的映射
(4)特性:

  • 数据卷可以在容器之间实现数据的共享和重用
  • 对数据卷内数据的修改会立即生效
  • 对数据卷的更新不会影响镜像
  • 数据卷会一直存在,直到没有容器使用
    (5)Demo演示
    在主机和容器之间创建数据卷,实现数据共享(共享目录)
docker run -it -v /root/mydatavolume:/root/container/mydatavolume centos /bin/bash
-v 指定数据卷的目录

默认:挂载的数据卷默认权限是读写(RW),也可以通过指定ro参数标识为只读

docker run -it -v /root/mydatavolume:/root/container/mydatavolume:ro centos /bin/bash
宿主机地址在前,容器地址在后。

(6)新版本的docker:使用命令: docker volume 命令管理数据卷
docker volume create ----> 也可以创建数据卷
(6)问题:Permission denied

原因:Centos 7的安全模块selinux把权限给禁掉了
(1)--privileged=true 加入到docker run中
(2)临时关闭SeLinux: setenforce 0

2、Docker的数据卷容器

(1)数据卷容器也是一个容器,目的:专门用来提供数据卷供其他的容器挂载
(2)实现在多个容器之间数据数据的共享
(3)Demo演示:创建数据卷容器
创建一个数据卷容器dbdatacontainer,在这个容器中创建一个数据卷挂载: /dbdata

docker run -it -v /dbdata --name dbdatacontainer centos

可以在其他的容器中使用 --volumes-from来挂载dbdatacontainer容器中的数据卷

docker run -it --volumes-from dbdatacontainer --name db1 centos
docker run -it --volumes-from dbdatacontainer --name db2 centos

3、利用数据卷容器来实现数据的迁移:数据的备份和恢复

备份与恢复的本质,就是借助数据卷这个在宿主机与容器之间的桥梁,让数据在宿主机与容器之间来回传递。

3.1、备份:使用下面的命令备份dbdatacontainer数据卷容器内的数据卷(tar包)

docker run --volumes-from dbdatacontainer -v $(pwd):/backup --name myworker centos tar cvf /backup/backup.tar /dbdata

3.2、恢复:如果要将数据恢复到一个容器中

  • 创建一个带有数据卷的容器
    docker run -it -v /dbdata --name dbdatacontainer2 centos

  • docker run -it --volumes-from dbdatacontainer2 -v $(pwd):/backup --name worker2 centos /bin/bash

六、Docker应用实战篇

1、Docker与数据库: MySQL

2、Docker与nginx

3、Docker与PHP

4、Docker与Python

5、Docker与Jupyter NootBook

6、Docker与TensorFlow

7、Docker与OpenStack的关系

七、搭建Harbor私有镜像仓库

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值