Docker容器技术入门与进阶实战
一、Docker概述
1、Docker是什么?
使用最广泛的开源容器引擎
一种操作系统级的虚拟化技术
依赖于Linux内核特性:Namespace(资源隔离)和Cgroups(资源限制)
一个简单的应用程序打包工具
2、Docker设计目标?
提供简单的应用程序打包工具
开发人员和运维人员职责逻辑分离
多环境保持一致性
3、Docker基本组成
Docker Client:客户端
Ddocker Daemon:守护进程
Docker Images:镜像
Docker Container:容器
Docker Registry:镜像仓库
4、容器 VS 虚拟机
5、Docker应用场景
应用程序打包和发布
应用程序隔离
持续集成
部署微服务
快速搭建测试环境
提供PaaS产品(平台即服务)
二、Linux安装Docker
1、 安装依赖包
[root@localhost ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
2、添加Docker软件包源
[root@localhost ~]# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
3、安装Docker CE
[root@localhost ~]# yum install -y docker-ce
4、启动Docker服务并设置开机启动
[root@localhost ~]# systemctl start docker.service [root@localhost ~]# systemctl enable docker.service
三、镜像管理
1、镜像是什么?
• 一个分层存储的文件
• 一个软件的环境
• 一个镜像可以创建N个容器
• 一种标准化的交付
• 一个不包含Linux内核而又精简的Linux操作系统
镜像不是一个单一的文件,而是有多层构成。我们可以通过docker history 查看镜像中各层内容及大小,每层 对应着Dockerfile中的一条指令。Docker镜像默认存储在/var/lib/docker/\<storage-driver\>中。
2、镜像从哪里来?
Docker Hub是由Docker公司负责维护的公共注册中心,包含大量的容器镜像,Docker工具默认从这个公共镜像库下载镜像。 地址:https://hub.docker.com/explore
配置镜像加速器:https://www.daocloud.io/mirror
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io
3、镜像与容器联系
如图,容器其实是在镜像的最上面加了一层读写层,在运行容器里文件改动时, 会先从镜像里要写的文件复制到容器自己的文件系统中(读写层)。
如果容器删除了,最上面的读写层也就删除了,改动也就丢失了。所以无论多 少个容器共享一个镜像,所做的写操作都是从镜像的文件系统中复制过来操作 的,并不会修改镜像的源文件,这种方式提高磁盘利用率。
若想持久化这些改动,可以通过docker commit 将容器保存成一个新镜像。
4、管理镜像常用命令
5、创建容器常用选项
6、容器资源限制
示例:
内存限额:
允许容器最多使用500M内存和100M的Swap,并禁用 OOM Killer:
docker run -d --name nginx03 --memory="500m" --memory-swap="600m" --oom-kill-disable nginx docker stats --no-stream nginx03 #查看内存情况
CPU限额:
允许容器最多使用一个半的CPU:
docker run -d --name nginx04 --cpus="1.5" nginx
允许容器最多使用50%的CPU:
docker run -d --name nginx05 --cpus=".5" nginx
7、管理容器常用命令
四、管理应用程序数据
1、 将数据从宿主机挂载到容器中的三种方式
• volumes:Docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)。保存数据的最佳方式。
• bind mounts:将宿主机上的任意位置的文件或者目录挂载到容器中。
• tmpfs:挂载存储在主机系统的内存中,而不会写入主机的文件系统。如果不希望将数据持久存储在任何位置,可以使用 tmpfs,同时避免写入容器可写层提高性能。
Volume
管理卷
[root@localhost ~]# docker volume inspect nginx_vol [root@localhost ~]# docker volume ls [root@localhost ~]# docker volume inspect nginx_vol
用卷创建一个容器
[root@localhost ~]# docker run -d --name nginx02 -p 88:80 --mount src=nginx_vol,dst=/usr/share/nginx/html nginx [root@localhost ~]# docker run -d --name nginx03 -p 89:80 -v nginx_vol:/usr/share/nginx/html nginx 两种创建方式一样
清理
[root@localhost ~]# docker stop nginx02 [root@localhost ~]# docker rm nginx02 [root@localhost ~]# docker volume rm nginx_vol
注意:
1. 如果没有指定卷,自动创建。
2. 建议使用--mount,更通用。
Bind Mounts
用卷创建一个容器
[root@localhost ~]# docker run -d --name nginx01 -p 88:80 --mount type=bind,src=/mnt/,dst=/usr/share/nginx/html nginx [root@localhost ~]# docker exec -it nginx01 bash root@1f5a5d245695:/# cd /usr/share/nginx/html/ root@1f5a5d245695:/usr/share/nginx/html# echo "hello nginx" >> index.html [root@localhost ~]# docker run -d --name nginx02 -p 89:80 -v /mnt/:/usr/share/nginx/html nginx
[root@localhost ~]# docker run -d --name nginx03 -p 90:80 --mount type=bind,src=/etc,dst=/opt nginx #把宿主机目录挂载到容器中
验证绑定
[root@localhost ~]# docker inspect nginx01
清理
[root@localhost ~]# docker stop nginx01 [root@localhost ~]# docker rm nginx01
注意:
1. 如果源文件/目录没有存在,不会自动创建,会抛出一个错误。
2. 如果挂载目标在容器中非空目录,则该目录现有内容将被隐藏。
小结
Volume特点:
• 多个运行容器之间共享数据。
• 当容器停止或被移除时,该卷依然存在。
• 多个容器可以同时挂载相同的卷。
• 当明确删除卷时,卷才会被删除。
• 将容器的数据存储在远程主机或其他存储上
• 将数据从一台Docker主机迁移到另一台时,先停止容器,然后备份卷的目录(/var/lib/docker/volumes/)
Bind Mounts特点:
• 从主机共享配置文件到容器。默认情况下,挂载主机/etc/resolv.conf到每个容器,提供DNS解析。
• 在Docker主机上的开发环境和容器之间共享源代码。例如,可以将Maven target目录挂载到容器中,每次在Docker主机 上构建Maven项目时,容器都可以访问构建的项目包。
• 当Docker主机的文件或目录结构保证与容器所需的绑定挂载一致时。
五、容器网络
1、网络模式
• bridge
–net=bridge
默认网络,Docker启动后创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。
• host
–net=host 容器不会获得一个独立的network namespace,而是与宿主机共用一个。这就意味着容器不会有自己的网卡信息,而是使用宿主 机的。容器除了网络,其他都是隔离的。
[root@localhost ~]# docker pull busybox #下载个镜像测试用
[root@localhost ~]# docker run -it --net=host busybox
• none
–net=none
获取独立的network namespace,但不为容器进行任何网络配置,需要我们手动配置。
• container
–net=container:Name/ID
与指定的容器使用同一个network namespace,具有同样的网络配置信息,两个容器除了网络,其他都还是隔离的。
[root@localhost ~]# docker run -itd --name bs -p 99:80 busybox [root@localhost ~]# docker run -d --name nginx01 --net=container:bs nginx #访问99端口可以访问nginx
• 自定义网络
与默认的bridge原理一样,但自定义网络具备内部DNS发现,可以通过容器名或者主机名容器之间网络通信。
[root@localhost ~]# docker network create bs-test [root@localhost ~]# docker run -it --name bs3 --net bs-test busybox [root@localhost ~]# docker run -it --name bs4 --net bs-test busybox #两个容器可以互相通
2、容器网络访问原理
3、桥接宿主机网络与配置固定IP地址
临时生效
#网桥名称 br_name=br0 #添加网桥 brctl addbr $br_name #给网桥设置IP ip addr add 192.168.35.6/17 dev $br_name #删除已存在的eth0网卡配置 ip addr del 192.168.35.6/17 dev ens192 #激活网桥 ip link set $br_name up #添加eth0到网桥 brctl addif $br_name ens192 #添加路由 ip route add default via 192.168.3.254 dev br0 #网关地址
永久生效
[root@localhost ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens192 TYPE=Ethernet DEVICE=ens192 ONBOOT=yes BRIDGE=br0 [root@localhost ~]# vim /etc/sysconfig/network-scripts/ifcfg-br0 DEVICE=br0 TYPE=Bridge ONBOOT=yes BOOTPROTO=static IPADDR=192.168.35.6 NETMASK=255.255.128.0 GATEWAY=192.168.3.254 DNS1=192.168.2.5 DNS2=192.168.2.6
还需要在Docker启动时桥接这个网桥
[root@localhost ~]# vim /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -b=br0 [root@localhost ~]# systemctl restart docker.service
pipework工具配置容器固定IP
[root@localhost ~]# git clone https://github.com/jpetazzo/pipework.git [root@localhost ~]# cp pipework/pipework /usr/bin/ [root@localhost ~]# docker run -itd --name bs6 --net none busybox [root@localhost ~]# pipework br0 bs6 192.168.35.8/17@192.168.3.254 [root@localhost ~]# docker exec -it bs6 sh
六、Dockerfile
1、 Dockerfile指令
2、Build镜像
Usage: docker build [OPTIONS] PATH | URL | - [flags] Options: -t, --tag list # 镜像名称 -f, --file string # 指定Dockerfile文件位置 # docker build . # docker build -t shykes/myapp . # docker build -t shykes/myapp -f /path/Dockerfile /path # docker build -t shykes/myapp http://www.example.com/Dockerfile
3、构建业务基础镜像
构建Nginx基础镜像
[root@localhost ~]# mkdir dockerfile/ [root@localhost ~]# cd dockerfile/ [root@localhost dockerfile]# vim Dockerfile-nginx FROM centos:7 MAINTAINER www.ctnrs.com RUN cd /etc/yum.repos.d/ && \ rm -rf * COPY CentOS-Base.repo /etc/yum.repos.d/ RUN yum clean all && \ yum repolist #上面为更换yum源操作,yum源能正常使用则不用更换 RUN yum install -y gcc gcc-c++ make \ openssl-devel pcre-devel gd-devel \ iproute net-tools telnet wget curl && \ yum clean all && \ rm -rf /var/cache/yum/* RUN wget http://nginx.org/download/nginx-1.15.5.tar.gz && \ tar zxf nginx-1.15.5.tar.gz && \ cd nginx-1.15.5 && \ ./configure --prefix=/usr/local/nginx \ --with-http_ssl_module \ --with-http_stub_status_module && \ make -j 4 && make install && \ rm -rf /usr/local/nginx/html/* && \ echo "ok" >> /usr/local/nginx/html/status.html && \ cd / && rm -rf nginx-1.12.2* && \ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ENV PATH $PATH:/usr/local/nginx/sbin #COPY nginx.conf /usr/local/nginx/conf/nginx.conf WORKDIR /usr/local/nginx EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] [root@localhost dockerfile]# docker build -t nginx:v1 -f Dockerfile-nginx . #构建镜像 [root@localhost dockerfile]# docker run -d --name nginx01 -p 88:80 nginx:v1 #运行镜像 下面举个例子用基础镜像构建业务镜像 [root@localhost dockerfile]# vim index.html #创建一个访问页面 [root@localhost dockerfile]# vim Dockerfile-nginx01 FROM nginx:v1 COPY index.html /usr/local/nginx/html/ [root@localhost dockerfile]# docker build -t nginx:v2 -f Dockerfile-nginx01 . [root@localhost dockerfile]# docker run -itd --name nginx02 -p 89:80 nginx:v2
构建PHP基础镜像
FROM centos:7 MAINTAINER www.ctnrs.com RUN cd /etc/yum.repos.d/ && \ rm -rf * COPY CentOS-Base.repo /etc/yum.repos.d/ RUN yum clean all && \ yum repolist RUN yum install epel-release -y && \ yum install -y gcc gcc-c++ make gd-devel libxml2-devel \ libcurl-devel libjpeg-devel libpng-devel openssl-devel \ libmcrypt-devel libxslt-devel libtidy-devel autoconf \ iproute net-tools telnet wget curl && \ yum clean all && \ rm -rf /var/cache/yum/* RUN wget http://docs.php.net/distributions/php-5.6.36.tar.gz && \ tar zxf php-5.6.36.tar.gz && \ cd php-5.6.36 && \ ./configure --prefix=/usr/local/php \ --with-config-file-path=/usr/local/php/etc \ --enable-fpm --enable-opcache \ --with-mysql --with-mysqli --with-pdo-mysql \ --with-openssl --with-zlib --with-curl --with-gd \ --with-jpeg-dir --with-png-dir --with-freetype-dir \ --enable-mbstring --with-mcrypt --enable-hash && \ make -j 4 && make install && \ cp php.ini-production /usr/local/php/etc/php.ini && \ cp sapi/fpm/php-fpm.conf /usr/local/php/etc/php-fpm.conf && \ sed -i "90a \daemonize = no" /usr/local/php/etc/php-fpm.conf && \ mkdir /usr/local/php/log && \ cd / && rm -rf php* && \ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ENV PATH $PATH:/usr/local/php/sbin:/usr/local/php/bin COPY php.ini /usr/local/php/etc/ COPY php-fpm.conf /usr/local/php/etc/ WORKDIR /usr/local/php EXPOSE 9000 CMD ["php-fpm"] [root@localhost dockerfile]# docker build -t php:v1 -f Dockerfile-php . [root@localhost dockerfile]# docker run -d --name php01 php:v1
构建Tomcat基础镜像
[root@localhost dockerfile]# vim Dockerfile-tomcat FROM centos:7 MAINTAINER www.ctnrs.com ENV VERSION=8.0.46 RUN cd /etc/yum.repos.d/ && \ rm -rf * COPY CentOS-Base.repo /etc/yum.repos.d/ RUN yum clean all && \ yum repolist RUN yum install java-1.8.0-openjdk wget curl unzip iproute net-tools -y && \ yum clean all && \ rm -rf /var/cache/yum/* RUN wget https://archive.apache.org/dist/tomcat/tomcat-8/v${VERSION}/bin/apache-tomcat-${VERSION}.tar.gz && \ #RUN wget http://192.168.31.211/apache-tomcat-${VERSION}.tar.gz && \ tar zxf apache-tomcat-${VERSION}.tar.gz && \ mv apache-tomcat-${VERSION} /usr/local/tomcat && \ rm -rf apache-tomcat-${VERSION}.tar.gz /usr/local/tomcat/webapps/* && \ mkdir /usr/local/tomcat/webapps/test && \ echo "ok" > /usr/local/tomcat/webapps/test/status.html && \ sed -i '1a JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom"' /usr/local/tomcat/bin/catalina.sh && \ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ENV PATH $PATH:/usr/local/tomcat/bin WORKDIR /usr/local/tomcat EXPOSE 8080 CMD ["catalina.sh", "run"] [root@localhost dockerfile]# docker build -t tomcat:v1 -f Dockerfile-tomcat . [root@localhost dockerfile]# docker run -itd --name tomcat01 -p 8089:8080 tomcat:v1 用浏览器测试访问:http://192.168.35.6:8089/test/status.html 用Tomcat基础镜像构建业务镜像 [root@localhost dockerfile]# vim Dockerfile-tomcat01 FROM tomcat:v1 COPY jenkins.war /usr/local/tomcat/webapps/ROOT.war #把war包放到Tomcat目录下,提前准备好war包 [root@localhost dockerfile]# docker build -t tomcat:v2 -f Dockerfile-tomcat01 . [root@localhost dockerfile]# docker run -itd --name tomcat02 -p 8088:8080 tomcat:v2 用浏览器测试访问:http://192.168.35.6:8088/
4、快速部署LNMP网站平台
自定义网络 [root@localhost dockerfile]# docker network create lnmp 创建Mysql容器 [root@localhost dockerfile]# docker run -d --name lnmp_mysql --net lnmp --mount src=mysql-vol,dst=/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress mysql:5.7 --character-set-server=utf8 创建PHP容器 [root@localhost dockerfile]# docker run -d --name lnmp_php --net lnmp --mount src=wwwroot,dst=/wwwroot php:v1 创建Nginx容器 [root@localhost dockerfile]# docker run -d --name lnmp_nginx --net lnmp -p 90:80 --mount type=bind,src=$(pwd)/nginx.conf,dst=/usr/local/nginx/conf/nginx.conf --mount src=wwwroot,dst=/wwwroot nginx:v1 以wordpress博客为例 [root@localhost dockerfile]# wget https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz [root@localhost dockerfile]# tar -xf wordpress-4.9.4-zh_CN.tar.gz [root@localhost dockerfile]# mv wordpress /var/lib/docker/volumes/wwwroot/_data/ 浏览器进行访问 http://192.168.35.6:90/wordpress/
七、企业级镜像仓库Harbor
1、Harbor概述
Habor是由VMWare公司开源的容器镜像仓库。事实上,Habor是在Docker Registry上进行了相应的 企业级扩展,从而获得了更加广泛的应用,这些新的企业级特性包括:管理用户界面,基于角色的访 问控制 ,AD/LDAP集成以及审计日志等,足以满足基本企业需求。
官方地址:https://vmware.github.io/harbor/cn/
2、 Harbor部署
Harbor安装有3种方式:
• 在线安装:从Docker Hub下载Harbor相关镜像,因此安装软件包非常小
• 离线安装:安装包包含部署的相关镜像,因此安装包比较大
• OVA安装程序:当用户具有vCenter环境时,使用此安装程序,在部署OVA后启动Harbor
接下来我们使用离线安装
首先要安装docker-compose工具 https://docs.docker.com/compose/install/ 有具体安装步骤 [root@Harbor ~]# curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose [root@Harbor ~]# chmod +x /usr/local/bin/docker-compose [root@Harbor ~]# ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose 接下来安装Harbor https://github.com/goharbor/harbor/releases 下载Harbor地址 先修改主机名,后面配置需要填写主机名,不然安装时会报错 [root@Harbor ~]# vim /etc/hostname Harbor [root@Harbor ~]# vim /etc/hosts 192.168.35.6 Harbor 修改完需要重启生效 [root@Harbor ~]# wget https://storage.googleapis.com/harbor-releases/harbor-offline-installer-v1.6.1.tgz [root@Harbor ~]# tar -xf harbor-offline-installer-v1.6.1.tgz [root@Harbor ~]# cd harbor/ [root@Harbor harbor]# vim harbor.cfg hostname = Harbor #本机的主机名 ui_url_protocol = http harbor_admin_password = 123456 #登录密码 [root@Harbor harbor]# ./prepare [root@Harbor harbor]# ./install.sh [root@Harbor harbor]# docker-compose ps #列出安装的文件 浏览器访问Harbor仓库 http://192.168.35.6/ #本机IP
3、Harbor仓库基本使用
我们使用的是http访问,所以要配置配置http镜像仓库可信任
[root@Harbor harbor]# docker info #查看是否配置 Insecure Registries: 127.0.0.0/8 查看Insecure Registries内容,这样说明没有配置 [root@Harbor harbor]# vim /etc/docker/daemon.json { "registry-mirrors": ["http://f1361db2.m.daocloud.io"], "insecure-registries": ["192.168.35.6"]} [root@Harbor harbor]# systemctl restart docker.service [root@Harbor harbor]# docker info Insecure Registries: 192.168.35.6 127.0.0.0/8 这样说明配置成功
接下来上传镜像到harbor仓库
[root@Harbor harbor]# docker tag nginx:v1 192.168.35.6/library/nginx:v1 #给上传镜像打TAG [root@Harbor harbor]# docker push 192.168.35.6/library/nginx #上传镜像到harbor仓库 0d7a34d5226d: Preparing ce0c1a98b514: Preparing 483e513c23d3: Preparing 296db778b4ae: Preparing 646e665acfc2: Preparing 877b494a9f30: Waiting denied: requested access to the resource is denied 这时会报错,这是因为我们没有登录,没有登录只能上传,不能下载
我们需要登录到harbor仓库创建一个用户
把新建用户加入到项目成员中
接下来我们进行登录,上传镜像到harbor仓库中
[root@Harbor harbor]# docker login 192.168.35.6 #登录harbor仓库 Username: lei Password: [root@Harbor harbor]# docker push 192.168.35.6/library/nginx #再次执行上传
我们在创建一个私有项目来测试一下
接下来对私有项目进行测试
上传镜像到私有项目 [root@Harbor harbor]# docker tag nginx:v2 192.168.35.6/progect/nginx:v2 [root@Harbor harbor]# docker push 192.168.35.6/progect/nginx 我们退出登录,分别下载公开项目和私有项目镜像试一下 [root@Harbor harbor]# docker logout 192.168.35.6 [root@Harbor harbor]# docker pull 192.168.35.6/library/nginx:v1 #下载公开项目正常 [root@Harbor harbor]# docker pull 192.168.35.6/progect/nginx:v2 #下载私有项目会报错,提示没有权限 [root@Harbor harbor]# docker login 192.168.35.6 #进行登录 [root@Harbor harbor]# docker pull 192.168.35.6/progect/nginx:v2 #登录后下载正常
八、图形页面管理
Portainer是一个开源、轻量级Docker管理用户界面,基于Docker API,可管理Docker主机或Swarm集群,支持最新版Docker和Swarm模式。
1、安装Portainer
官方安装https://www.portainer.io/installation/文档
1、创建卷 [root@Harbor ~]# docker volume create portainer_data 2、创建Portainer容器 [root@Harbor ~]# docker run -d -p 8000:8000 -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
2、测试安装完的Portainer
访问http://192.168.35.6:9000/ 第一次登陆需要让你创建用户名密码,这里我们选择本地登录