Docker容器技术入门与进阶实战学习笔记
本文档介绍 Docker容器技术入门与进阶实战学习笔记 的相关内容。
分配一个伪终端
docker run -i -t centos /bin/bash docker run -it centos /bin/bash # 如果镜像不存在,会自动去官方下载 安装docker环境
参考官方文档:docs.docker.com
https://docs.docker.com/install/linux/docker-ce/centos/
安装依赖包
yum install -y yum-utils device-mapper-persistent-data lvm2 安装docker-ce源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 安装docker
yum install -y docker-ce 设置开机启动并启动docker
systemctl enable docker systemctl start docker 测试docker
docker run hello-world 查看docker详细信息
docker info 查看docker版本信息
docker version 创建一个容器(自动下载一个容器)
docker run -it nginx 查看容器信息(查看ip信息)
docker inspect <ID/NAME> 进入容器
docker exec -it <ID/NAME> /bin/bash 运行并进入容器
docker run -it <ID/NAME> /bin/bash 查看容器资源限制
docker stats <ID/NAME> docker ststs --no-stream <ID/NAME> # 查看CPU限制 强制删除正在运行的容器
docker rm -f $(docker ps -a |awk '{print $1}') 测试镜像:
docker run -it busybox # 测试用镜像 镜像是什么:
- 一个分层存储的文件
- 一个软件的环境
- 一个镜像可以创建N个容器
- 一个标准化的交付方式
- 一个不包含Linux内核而又精简的Linux操作系统
镜像不是一个单一的文件,而是有多层构成。我们可以通过docker history <ID/NAME>查看镜像中各层内容及大小,每层对应着Dockerfile中的一条指令。Docker镜像默认存储在/var/lib/docker/\<storage-driver\>中。 查看镜像有哪些分层
docker history nginx 检索镜像
docker search nginx 配置镜像加速
# https://www.daocloud.io/mirror curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io # cat /etc/docker/daemon.json { "registry-mirrors": ["http://f1361db2.m.daocloud.io"] } # 配置完成后重启docker systemctl restart docker 下载一个镜像
docker pull centos 如图,容器其实是在镜像的最上面加了一层读写层,在运行容器里文件改动时,会先从镜像里要写的文件复制到容器自己的文件系统中(读写层)。
如果容器删除了,最上面的读写层也就删除了,改动也就丢失了。所以无论多少个容器共享一个镜像,所做的写操作都是从镜像的文件系统中复制过来操作的,并不会修改镜像的源文件,这种方式提高磁盘的利用率。
若想持久化这些改动。可以通过docker commit将容器保存成一个新镜像
镜像管理
管理镜像常用命令
docker image COMMAND
| 指令 | 描述 |
|---|---|
| ls | 列出镜像 |
| build | 构建镜像来自Dockerfile |
| history | 查看镜像历史 |
| inspect | 显示一个或多个镜像详细信息 |
| pull | 从镜像创建拉取镜像 |
| push | 推送一个镜像到镜像仓库 |
| rm | 移除一个或多个镜像 |
| prune | 移除未使用的镜像。没有被标记或被任何容器引用的 |
| tag | 创建一个引用源镜像标记目标镜像 |
| export | 导出容器文件系统到tar归档文件 |
| import | 导入容器文件系统tar归档文件创建镜像 |
| save | 保存一个或多个镜像到一个tar归档文件 |
| load | 加载镜像来自tar归档或标准输入 |
保存一个镜像,完整导出
docker image save nginx > nginx.tar 加载导入一个镜像
docker image load < nginx.tar 容器管理
管理容器的常用命令
docker container run COMMAND
docker run COMMAND # 老的命令
| 选项 | 描述 |
|---|---|
| - i, -interactive | 交互式 |
| - t, -tty | 分配一个伪终端 |
| - d, -detach | 运行容器到后台 |
| - e, -env | 设置环境变量 |
| - p, -publish list | 发布容器端口到主机 |
| - P, -publish-all | 发布容器所有EXPOSE的端口到宿主机随机端口 |
| - name string | 指定容器名称 |
| - h, -hostname | 设置容器主机名 |
| - ip, string | 指定容器ip, 只能用于自定义网络 |
| - network | 连接容器到一个网络 |
| - mount mount | 将文件系统附加到容器 |
| - v, -volume list | 绑定挂载一个卷 |
| - restart string | 容器退出时重启策略,默认no, 可选值:[always(开机启动) \ |
限制容器资源的常用命令
docker container run COMMAND
| 选项 | 描述 |
|---|---|
| - m, -memory | 容器可以使用的最大内存量 |
| - memory-swap | 允许交换到磁盘的内存量 |
| - memory-swappiness=<0-100> | 容器使用SWAP分区交换的百分比(0-100, 默认为-1) |
| - oom-kill-disable | 禁用OOM Killer |
| - cpus | 可以使用的CPU数量 |
| - cpuset-cpus | 限制容器使用特定的CPU核心,如(0-3,0,1) |
| - cpu-shares | CPU共享(相对权重) |
示例:
内存限额:
允许容器最多使用500M内存和100Mswap,并禁用OOM Killer:
docker run -d --name nginx --memory="500m" --memory-swap="600m" --oom-kill-disable nginx 不设置Swap,将memory、memory-swap 的值设置为一样
docker run -d --name nginx --memory="500m" --memory-swap="500m" --oom-kill-disable nginx CPU限额:
允许容器最多使用1个半的CPU:
docker run -d --name nginx --cpus="1.5" nginx 允许容器最多使用50%的CPU:
docker run -d --name nginx --cpus=".5" nginx 查看管理容器的常用命令
| 选项 | 描述 |
|---|---|
| ls | 列出容器 |
| inspect | 查看一个或多个容器详细信息 |
| exec | 在运行容器中执行命令 |
| commit | 创建一个新镜像来自一个容器 |
| cp | 拷贝文件/文件夹到一个容器 |
| logs | 获取一个容器日志 |
| port | 列出或指定容器端口映射 |
| top | 显示一个容器运行的进程 |
| stats | 显示容器资源使用统计 |
| stop/start | 停止/启动一个或多个容器 |
| rm | 删除一个或多个容器 |
列出刚创建的容器
docker ps -l 列出所有容器
docker ps -a 管理应用程序数据
将数据从宿主机挂载到容器的三种方式
Docker 提供三种方式将数据从宿主机挂载到容器中
Volume
管理卷
docker volume create nginx-vol docker volume ls docker volume inspect nginx-vol 用卷创建一个容器
docker run -d -it --name=nginx-test --mount src=nginx-vol,dst=/usr/share/nginx/html nginx docker run -d -it --name=nginx-test -v nginx-vol:/usr/share/nginx/html nginx 清理
docker stop nginx-test docker rm nginx-test docker volume rm nginx-vol 注意:
- 如果没有指定卷,自动创建。
- 建议使用
--mount, 更通用。
Bind Mounts
用卷创建一个容器
docker run -d -it --name=nginx-test --mount type=bind,src=/app/wwwroot,dst=/usr/share/nginx/html nginx docker run -d -it --name=nginx-test -v /app/wwwroot:/usr/share/nginx/html nginx 验证绑定
docker inspect nginx-test 清理
docker stop nginx-test docker rm nginx-test 注意:
- 如果源文件/目录没有存在,不会自动创建,会抛出一个错误
- 如果挂载目标在容器中非空目录,则该目录现有内容将被影藏
总结:
Volume 特点:
- 多个运行容器之间共享数据。
- 当容器停止或被移除时,该卷依然存在
- 多个容器可以同时挂载相同的卷
- 当明确删除时,卷才会被删除
- 将容器的数据存储在远程主机或其它存储上
- 将数据从一台Docker主机迁移到另一台时,先停止容器,然后备份卷的目录
/var/lib/docker/volumes/
Bind Mounts特点:
- 从主机共享配置文件到容器。默认情况下,挂载主机
/etc/resolv.conf到每个容器,提供DNS解析 - 在Docker主机上的开发环境和容器之间共享源代码。例如,可以将maven target目录挂载到容器中,每次在Doeker主机上构建maven项目时,容器都可以访问构建的项目包。
当Docker主机的文件或目录结构保证与容器所需的绑定挂载一致时
容器网络
网络模式
- bridge:
net = bridge
默认网络,Docker启动后创建一个Docker0网桥,默认创建的容器也是添加到这个网桥中- host:
net = host
容器不会获得一个独立的network namespace, 而是与宿主机共用一个。这就意味着容器不会有自己的网卡信息,而是使用宿主机的。容器除了网络,其它都是隔离的- none
net = none
获取独立的network namespace, 但不为容器进行任何网络配置,需要我们手动配置- container
net = container:Name/ID
与指定的容器使用同一个network namespace, 具有同样的网络配置信息,两个容器除了网络,其他都还是隔离的- 自定义网络
与默认的bridge原理一样,但自定义网络具备内部DNS发现,可以通过容器名或者主机名容器之间网络通信
桥接宿主机网络与配置固定IP地址
临时生效
# 网桥名称 br_name=br0 # 添加网桥 brctl addbr $br_name # 给网桥设置ip ip addr add 192.168.1.120/24 dev $br_name # 删除已存在的eth0网卡配置 ip addr del 192.168.1.120/24 dev eth0 # 激动网桥 ip link set $br_name up # 添加eth0到网桥 brctl addif $br_name eth0 # 添加路由 ip route add default via 192.168.1.1 dev br0 还需要在Docker启动时桥接这个网桥:
# vim /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd -b=br0 # systemctl daemon-reload # systemctl restart docker 永久生效
# vim /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 TYPE=Ethernet ONBOOT=yes BRIDGE=br0 # vim /etc/sysconfig/network-scripts/ifcfg-br0 DEVICE=br0 TYPE=Bridge ONBOOT=yes BOOTPROTO=static IPADDR=192.168.1.120 NETMASK=1.2.3.4 GATEWAY=192.168.1.1 DNS1=1.2.3.4 配置固定IP
C_ID=$(docker run -itd --name=none ubuntu) C_PID=$(docker inspect -f '{{.State.Pid}}' $C_ID) # 创建network namespace目录并将容器的network namespace软连接到些目录,以便ip netns命令读取 mkdir -p /var/run/netns ls -n /proc/$C_PID/ns/net /var/run/netns/$C_PID # 添加虚拟网卡veth+容器PID,类型是veth pair, 名称是vp+容器PID ip link add veth$C_PID type veth peer name vp$C_PID # 添加虚拟网卡到br0网桥 brctl addif br0 veth$C_PID # 激活虚拟网卡 ip link set veth$C_PID up # 设置容器网络信息 IP='192.168.1.124/24' GW='192.168.1.1' # 给进程配置一个network namespace ip link set vp$C_PID netns $C_PID # 在容器进程里面设置网卡信息 ip netns exec $C_PID ip link set dev vp$C_PID name eth0 ip netns exec $C_PID ip link set eth0 up ip netns exec $C_PID ip addr add $IP dev eth0 ip netns exec $C_PID ip route add default via 192.168.1.1 pipework工具配置容器固定ip
git clone https://github.com/jpetazzo/pipework.git cp pipework/pipework /usr/local/bin docker run -itd --net=none --name test1 ubuntu pipework br0 test1 192.168.1.122/24@192.168.1.1 镜像制作Dockerfile
Dockerfile 介绍
基本格式
FROM centos:latest MAINTAINER jeff RUN yum install gcc -y COPY run.sh /usr/bin EXPOSE 80 CMD ["run.sh"] Dockerfile常用指令 | 指令 | 描述 | | — | — | | FROM | 构建新镜像是基于哪个镜像 | | MAINTAINER | 镜像维护者姓名或邮箱地址 | | RUN | 构建镜像时运行的shell命令 | | COPY | 拷贝文件或目录到镜像中 | | ENV | 设置环境变量 | | USER | 为RUN、CMD和ENTRYPOINT执行命令指定运行用户 | | EXPOSE | 声明容器运行的服务端口 | | HEALTHCHECK | 容器中服务健康检查 | | WORKDIR | 为RUN、CMD、ENTRYPOINT、COPY和ADD设置工作目录 | | ENTRYPOINT | 运行容器时执行,如果有多个ENTRYPOINT指令,最后一个生效 | | CMD | 运行容器时执行,如果有多个CMD指令,最后一个生效 |
Build镜像
Usage: docker build [OPTIONS] PATH | URL | - [flags] Options: t, --tag list # 镜像名称 f, --file string # 指定Dockerfile文件位置 # docker build . # docker build -t jeff/myapp . # docker build -t jeff/myapp -f /path/Dockerfile /path # docker build -t jeff/myall http://www.example.com/Dockerfile 构建Nginx基础镜像
步骤:
- yum或者源码编译安装(1. configure 2. make 3. make install) RUN
- 启用哪些模块 RUN
- nginx 初始化 RUN
- 启动 CMD ENTRIPOINT
Dockerfile-nginx
FROM centos:7 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.15.5* && \ 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;"] # docker build -t nginx:v1 -f Dockerfile-nginx . Dockerfile-php
FROM centos:7 MAINTAINER xsbloc.com RUN yum install -y epel-release -y && \ yum install -y gcc gcc-c++ make gd-devel libxml2-devlel \ 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 \ -enalbe-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"] # docker build -t php:v1 -f Dockerfile-php . Dockerfile-Tomcat
FROM centos:7 MAINTAINER xsbloc.com ENV VERSION=8.0.46 RUN yum install -y java-1.8-openjdk wget curl unzip iproute net-tools && \ yum clean all && \ rm -rf /var/cache/yum/* 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 -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ENV PATH $PATH:/usr/local/tomcat/bin WORKDIR /usr/local/tomcat EXPOSE 8080 CMD ["catalina.sh", "run"] 快速部署LNMP网站平台并项目测试
- 自定义网络
docker network create lnmp - 创建Mysql容器
docker run -d \ -name lnmp_mysql \ -net lnmp \ -mount src=mysql-vol,dst=var/lib/mysql \ e MYSQL_ROOT_PASSRORD=123456 -e MYSQL_DATABASE=wordpress mysql:5.7 --character-set-server=utf8 - 创建PHP容器
docker run -d --name lnmp_php --net lnmp --mount src=wwwroot,dst=/wwwroot php:v1 - 创建nginx容器
docker run -d --name lnmp_nginx --net lnmp -p 88:80 \ -mount type=bind,src=$(pwd)/nginx.conf,dst=/usr/local/nginx/conf/nginx.conf --mount src=wwwroot,dst=/wwwroot nginx:v1 - 以wordpress博客为例
https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tat.gz 企业级镜像创建Harbor
Harbor 概述
Harbor是由VMWare公司开源的容器镜像创建。事实上,Habor是在Docker Registry上进行了相应的企业级扩展,从而获得了更加广泛的应用,这些新的企业级特性包括:管理用户界面,基于角色的访问控制,AD/LADP集成以及审计日志等,足以满足基本企业需求。
官方地址:https://vmware.github.io/harbor/cn/
| 组件 | 功能 |
|---|---|
| harbor-adminiserver | 配置管理中心 |
| harbor-db | Mysql数据库 |
| harbor-jobservice | 负载镜像复制 |
| harbor-log | 记录操作日志 |
| harbor-ui | Web管理页面和API |
| nginx | 前端代理,负责前端页面和镜像上传/下载转发 |
| redis | 会话 |
| registry | 镜像存储 |
Harbor部署
# github下载稳定版本,需要docker-compose编排工具 # tar zxvf harbor-offline-install-v1.5.1.tgz # cd harbor # vim harbor.cfg hostname = 192.168.1.120 # ip或域名 ui_url_protocol = http # 对外最好使用https harbor_admin_password = YOUR_PASSWORD # ./prepare # ./install.sh Harbor基本使用
- 配置http镜像仓库可信任
# 非https需要添加可信任 # vim /etc/docker/daemon.json {"insecure-registries":["reg.xsbloc.com"]} # systemctl restart docker - 打标签
docker tag centos:6 reg.xsbloc.com/jeff/centos:6 上传 docker push reg.xsbloc.com/jeff/centos:6
下载 docker pull reg.xsbloc.com/jeff/centos:6 —
图形化管理Portainer
portainer
portainer是一个开源、轻量级Docker管理用户界面,基于Docker API,可管理Docker主机或Swarm集群,支持最新版Docker和Swarm模式
- 创建卷
docker volume create portainer_data - 创建portainer容器
docker run -d \ p 9000:9000 \ -v /var/run/docker.sock:/var/run/docker.sock \ -v portainer_data:/data \ portainer/portainer 构建Docker容器监控系统
Prometheus
prometheus特点
- 多维数据模型:由度量名称和键值对标识的时间序列数据
- PromSQL:一种灵活的查询语言,可以利用多数据完成复杂的查询
- 不依赖分布式存储,单个服务器节点可直接工作
- 基于http的pull方式采集时间序列数据
- 推送时间序列数据通过PushGateway组件支持
- 通过服务发现或静态配置发现目标
- 多种图形模式及仪表盘支持(grafana)
- Prometheus Server: 收集指标和存储时间序列数据,并提供查询接口
- ClientLibrary:客户端库
- Push Gateway: 短期存储指标数据。主要用于临时性的任务
- Exporters:采集已有的第三方服务监控指标并暴露metrics
- Alertmanager:告警
- Web UI:简单的Web控制台
实例:可以抓取的目标名称为实例(Instances) 作业:具有相同目标的实例集合称为作业(Job)
scrape_configs: job_name:'prometheus' static_configs: targets:['localhost:9090'] job_name:'node' static_configs: targets:['192.168.1.120:9090'] 部署可以参考官方网站,直接使用docker进行部署
cAdvisor(Container Advisor)用于收集正在运行的容器资源使用和性能信息。
https://github.com/google/cadvisor # 项目地址直接使用容器运行 Grafana是一个开源的度量分析和可视见系统 (docker模板id:193)