Docker概述
什么是容器
- 容器技术已经成为应用程序封装和交付的核心技术
- 容器技术的核心有以下几个内核技术组成:
Cgroups(Control Groups)-资源管理
NameSpace-进程管理
SELinux安全 - 由于是在物理机上实施的隔离,启动一个容器,可以像启动一个进程一样快速
什么是Docker
- Docker是完整的一套容器管理系统
- Docker提供了一组命令,让用户更加方便直接的使用容器技术,而不需要过多的关心底层内核技术
Docker特性
Docker优点
- 相比于传统的虚拟化技术,容器更加简洁高效
- 传统虚拟机需要给每个VM安装操作系统
- 容器使用的共享公共库和程序
Docker缺点
- 容器的隔离性没有虚拟化强
- 公用Linux内核,安全性有先天性缺陷
- SELinux难以驾驭
- 监控容器和容器排错是挑战
Docker部署
[root@docker01 ~]# yum -y install docker
[root@docker01 ~]# systemctl restart docker
[root@docker01 ~]# systemctl enable docker
Docker镜像
基本概念
什么是镜像
- 在Docker中容器是基于镜像启动
- 镜像是启动容器的核心
- 镜像采用分层设计
- 使用快照的COW设计,确保底层数据不丢失
Docker hub镜像仓库
[root@docker1 ~]# docker search busybox
[root@docker1 ~]# docker search centos
[root@docker1 ~]# docker search nginx
下载、上传镜像
- 下载镜像(从镜像仓库中下载镜像)
[root@docker1 ~]# docker help pull
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
[root@docker1 ~]# docker pull docker.io/busybox
- 上传镜像(上传镜像到仓库)
[root@docker1 ~]# docker help push
Usage: docker push [OPTIONS] NAME[:TAG]
[root@docker1 ~]# docker push docker.io/busybox
导入、导出镜像
- 导出镜像(将本地镜像导出为tar文件)
[root@docker1 ~]# docker save docker.io/busybox:latest -o busybox.tar
[root@docker1 ~]# ls
- 导入镜像(通过tar包文件导入镜像)
[root@docker1~]# scp busybox.tar root@192.168.1.31:/root
[root@docker2~]# ls
busybox.tar
[root@docker2~]# docker load -i busybox.tar
[root@docker2~]# docker images
启动镜像
- 启动centos镜像生成一个容器
[root@docker1 ~]# docker images
[root@docker1 ~]# docker run -it docker.io/centos:latest /bin/bash
/bin/bash是容器内命令
- 开启另一个终端(查看容器信息)
[root@docker1 ~]# docker ps -a
镜像常用命令
命令列表
- docker images //查看镜像列表
- docker history //查看镜像制作历史
- docker inspect //查看镜像底层信息
- docker pull //下载镜像
- docker push //上传镜像
- docker rmi //删除本地镜像
- docker save //镜像另存为tar包
- docker load //使用tar包导入镜像
- docker search //搜索镜像
- docker tag //修改镜像名称和标签
docker images
查看镜像列表
- 镜像仓库名称
- 镜像标签
- 镜像ID
- 创建时间
- 大小
[root@docker1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/busybox latest d8233ab899d4 10 days ago 1.199 MB
docker history
查看镜像历史
- 了解镜像制作过程
- 详细参考后面的dockerfile内容
[root@docker1 ~]# docker history docker.io/centos
docker inspect
查看镜像底层信息
- 了解镜像环境变量、存储卷、标签等信息
[root@docker1 ~]# docker inspect docker.io/centos
docker rmi
删除本地镜像
- 注意:启动容器时删除镜像会提示错误
- 强制删除加 -f
[root@docker1 ~]# docker rmi docker.io/centos
docker save|load
保存本地镜像另存为tar文件
- 方便其他人使用tar包导入镜像
[root@docker1 ~]# docker save docker.io/busybox:latest -o busybox.tar
[root@docker1 ~]# ls busybox.tar
busybox.tar
- 使用tar包文件导入镜像
[root@docker1 ~]# docker load -i busybox.tar
docker tag
重命名镜像名称(复制)
[root@docker1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/centos latest 42b4762643dc 4 weeks ago 109.2M
[root@docker1 ~]# docker tag docker.io/centos:latest cen:v1
[root@docker1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
cen v1 76d6bc25b8a5 4 months ago 199.7 MB
容器常用命令
命令列表
- docker run //运行容器
- docker ps //查看容器列表
- docker stop //关闭容器
- docker start //启动容器
- docker restart //重启容器
- docker attach|exec //进入容器
- docker inspect //查看容器底层信息
- docker top //查看容器进程列表
- docker rm //删除容器
docker run
使用镜像启动容器
[root@docker1 ~]# docker run -it docker.io/centos:latest bash //i交互式,t终端
[root@docker02 ~]# docker run -p 8081:80 -it docker.io/centos //启动容器,将容器的80端口映射到本机的8081端口
当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:
1)检查本地是否存在指定的镜像,不存在就从公有仓库下载
2)利用镜像创建并启动一个容器
3)分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
4)从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
5)从地址池配置一个 ip 地址给容器
6)执行用户指定的应用程序
7)执行完毕后容器被终止
[root@bbb51ac87b08 /]#exit //直接杀死进程退出
[root@bbb51ac87b08 /]#Ctrl + p + q //不杀死进程退出
[root@docker1 ~]# docker run -itd docker.io/centos:latest bash //d后台进程
b8f218f2341c12655e6092d7d2e7fd5229824fdefce84075fb3a9569ebf82079
[root@docker1 ~]# docker ps
docker ps
列出容器列表
- docker ps 查看正在运行的容器
- docker ps -a 查看所有容器列表
- docker ps -aq 仅显示容器id
[root@docker1 ~]# docker ps
[root@docker1 ~]# docker ps -a
docker stop|start|restart
管理容器
- docker stop 关闭容器
- docker start 开启容器
- docker restart 重启容器
[root@docker1 ~]# docker ps
[root@docker1 ~]# docker stop b8f
docker attach|exec
进入容器
- docker attach 进入容器,exit会导致容器关闭
- docker exec 进入容器,退出时不会关闭容器
[root@docker1 ~]# docker ps
[root@docker1 ~]# docker attach b8f //b8f容器id
[root@docker1 ~]# docker exec -it 7e4e bash
docker inspect
查看容器底层信息
[root@docker1 ~]# docker ps
[root@docker1 ~]# docker inspect 7e4e
docker top
查看容器进程列表
[root@docker1 ~]# docker ps
[root@docker1 ~]# docker top 7e4e
docker rm
删除容器
- 注意,删除正在运行的容器时会提示错误,加-f强制删除
[root@docker1 ~]# docker rm 7e4e
[root@docker1 ~]# docker rm $(docker ps -aq)
给容器cenos内安装httpd软件,不能用systemctl启动,需要修改配置文件httpd.conf将#ServerName www.example.com:80修改成ServerName localhost:80,然后执行httpd启动服务
容器nginx内使用的是ubantu系统,先执行apt-get update,然后dpkg -L nginx查询相关配置文件
使用apt-cache search +指令 查询该指令对应的安装包
自定义镜像
docker commit
- 使用镜像启动容器,在该容器基础上修改
- 另存为一个新镜像
[root@docker1 docker_images]# docker run -it docker.io/centos
修改(增删改数据、安装软件、修改配置文件等)
[root@docker1 docker_images]# docker ps
[root@docker1 docker_images]# docker commit 8d07ecd7e345 docker.io/myos:lastest //将cenos提交为一个新的镜像
-p 参数把容器端口和宿主机端口绑定,客户端可以通过访问宿主机ip+宿主机的绑定端口来访问容器内服务
[root@docker01 ~]# docker run -it -p 8080:80 docker.io/myos:lastest //创建一个新的容器,将宿主机的8080端口绑定到容器的80端口
[root@docker01 ~]# docker history docker.io/myos:lastest //查看该镜像的层级结构
Dockerfile
Dockerfile语法格式
- FROM:基础镜像
- MAINTAINER:镜像创建者信息
- EXPOSE:开放的端口
- ENV:设置变量
- ADD:复制文件到镜像
- RUN:制作镜像时执行的命令,可以有多个
- WORKDIR:定义容器默认工作目录
- CMD:容器启动时执行的命令,仅可以有一条CMD
Dockerfile文件案例
[root@docker1 build]# cat Dockerfile
FROM docker.io/myos:latest
MAINTAINER Jacob redhat@163.com
RUN yum -y install httpd
ENV EnvironmentFile=/etc/sysconfig/httpd
WORKDIR /var/www/html/ //定义容器默认工作目录
ADD index.html index.html
EXPOSE 80 //设置开放端口号
EXPOSE 443
CMD ["httpd", "-DFOREGROUND"]
使用Dockerfile工作流程
- mkdir build; cd build
- vim Dockerfile
- docker build -t imagename Dockerfile所在目录
[root@docker01 ~]# mkdir aa
[root@docker01 ~]# cd aa
[root@docker01 aa]# vim Dockerfile //创建Dockerfile
FROM docker.io/centos:latest //源镜像
RUN rm -f /etc/yum.repos.d/*.repo //移除源镜像目录下的内容
ADD local.repo /etc/yum.repos.d/local.repo //将本地文件导入到源镜像目录下
RUN yum -y install net-tools vim psmisc tree lftp iproute //yum装包
RUN yum clean all //清除缓存
//编辑本地的yum文件
//注:该文件必须跟Dockerfile在同一目录下
[root@docker01 ~]# vim aa/local.repo
[local]
name=local
enabled=1
gpgcheck=0
baseurl=ftp://192.168.1.254/centos-1804
//根据Dockerfile创建新的镜像
[root@docker01 ~]# docker build -t myos:test aa/
创建一个http镜像
查看http的启动脚本
cat /usr/lib/systemd/system/httpd.service
[root@docker01 ~]# mkdir http
[root@docker01 ~]# vim http/Dockerfile
FROM myos:test
RUN rm -f /etc/yum.repos.d/*.repo
ADD local.repo /etc/yum.repos.d/local.repo
RUN yum -y install httpd
ENV EnvironmentFile=/etc/sysconfig/httpd
WORKDIR /var/www/html/
ADD index.html index.html
EXPOSE 80
EXPOSE 443
RUN sed -i 's/#ServerName www.example.com:80/ServerName localhost:80/g' /etc/httpd/conf/httpd.conf
RUN /usr/sbin/httpd
#CMD ["/usr/sbin/httpd", "-DFOREGROUND"]
[root@docker01 ~]# cp aa/local.repo http/
[root@docker01 ~]# echo "hello http" > http/index.html
[root@docker01 ~]# docker build -t myos:http http/
自定义镜像仓库
registry基本概念
- 共享镜像的一台服务器(镜像化的一台服务器)
自定义私有仓库
安装私有仓库(服务端)
- yum install docker-distribution
启动私有仓库,并设置开机自启动
- systemctl start docker-distribution
- systemctl enable docker-distribution
仓库配置文件及数据存储路径
- /etc/docker-distribution/registry/config.yml
- /var/lib/registry
[root@docker01 ~]# yum -y install docker-distribution
[root@docker01 ~]# systemctl start docker-distribution
[root@docker01 ~]# systemctl enable docker-distribution
测试
[root@docker01 ~]# curl localhost:5000/v2/
{}
自定义私有仓库
客户端配置:
- 修改配置文件 /etc/sysconfig/docker
[root@docker01 ~]# vim /etc/sysconfig/docker
... ...
ADD_REGISTRY='--add-registry docker01:5000' //仓库地址
INSECURE_REGISTRY='--insecure-registry docker01:5000' //允许非加密方式访问仓库
... ...
//重启服务
[root@docker01 ~]# systemctl restart docker
为镜像创建标签:
- 这里的地址要写 宿主机 的 IP 地址或主机名
- docker tag 镜像:标签 IP:5000/镜像:latest
上传镜像
- 上传镜像的标签内包含地址和端口号
- docker push IP:5000/镜像:latest
[root@docker01 ~]# docker tag myos:http docker01:5000/myos:latest
[root@docker01 ~]# docker push docker01:5000/myos:latest
远程启动容器(docker2)
- 配置 /etc/sysconfig/docker
[root@docker02 ~]# vim /etc/sysconfig/docker
... ...
ADD_REGISTRY='--add-registry docker01:5000' //仓库地址
INSECURE_REGISTRY='--insecure-registry docker01:5000' //允许非加密方式访问仓库
... ...
//重启服务
[root@docker02 ~]# systemctl restart docker
//docker02配置本地域名解析
[root@docker02 ~]# vim /etc/hosts
... ...
192.168.1.30 docker01
... ...
//远程拉取镜像
[root@docker02 ~]# docker run -it docker01:5000/myos:latest
//查看私有镜像仓库中的 镜像名称
[root@docker02 ~]# curl http://docker01:5000/v2/_catalog
{"repositories":["myos"]}
//查看某一仓库的标签
[root@docker02 ~]# curl http://docker01:5000/v2/myos/tags/list
{"name":"myos","tags":["latest","test"]}
进入registry 的配置文件,进入容器查看
- /etc/docker/registry/config.yml
持久化存储
存储卷
卷的概念
- docker容器不保持任何数据
- 重要数据请使用外部卷存储(数据持久化)
- 容器可以挂载真实机目录或共享存储为卷
主机卷的映射
- 将真实机目录挂载到容器中提供持久化存储
- 目录不存在就自动创建
- 目录存在就直接覆盖掉
[root@docker01~]# docker run -v /data:/data -it docker.io/centos
bash
共享存储
共享存储基本概念
- 一台共享存储服务器可以提供给所有Docker主机使用
- 共享存储服务器(NAS、SAN、DAS等)
- 如:
- 使用NFS创建共享存储服务器
- 客户端挂载NFS共享,并最终映射到容器中
一,创建一台虚拟机nfs(192.168.1.32),安装nsf
[root@nfs ~]# yum -y install nfs-utils
[root@nfs ~]# mkdir public
[root@nfs ~]# chmod -R 777 public/
[root@nfs ~]# echo "hello world" > public/index.html
[root@nfs ~]# vim /etc/exports
/root/public *(rw)
[root@nfs ~]# systemctl restart nfs
二,docker01和docker02上创建挂载目录并安装nsf,启动服务(docker02做同样操作)
[root@docker01 ~]# mkdir public
[root@docker01 ~]# yum -y install nfs-utils
[root@docker01 ~]# systemctl restart nfs
[root@docker01 ~]# systemctl enable nfs
[root@docker01 ~]# vim /etc/fstab
... ...
192.168.1.32:/root/public /root/public nfs defaults 0 0
[root@docker01 ~]# mount -a
三,创建容器,指定容器的共享目录(docker02做同样操作)
//将本地的nsf的public目录挂载到容器的/var/www/html的目录下
[root@docker01 ~]# docker run -it -v /root/public:/var/www/html myos:http bash
四,测试(docker02做同样操作)
[root@docker01 ~]# curl 172.17.0.2
Docker网络架构
Docker网络拓扑
查看Docker默认网络模型
查看默认Docker创建的网络模型
[root@docker1~]# docker network list
[root@docker1~]# ip a s docker0
[root@docker1~]# brctl show docker0 //启动容器会绑定该网桥
使用Docker创建网桥
- 新建Docker网络模型
[root@docker01~]# docker network create --subnet=10.10.10.0/24 docker1
[root@docker01~]# docker network list
[root@docker01~]# ip a s
[root@docker01~]# docker network inspect docker1
使用自定义网桥
- 启动容器,使用刚刚创建的自定义网桥
[root@docker01 ~]# docker run --network=docker1 -itd myos:http