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/ 第一次登陆需要让你创建用户名密码,这里我们选择本地登录

 

posted @ 2019-11-20 14:43  Null°  阅读(450)  评论(0编辑  收藏  举报