Docker入门笔记

目录

  1. 二进制安装Docker 1
  2. Docker镜像管理 2
    2.1. 镜像是什么 2
    2.2. 镜像与容器联系 2
    2.3. 管理镜像常用命令 2
    2.3.1. docke查看镜像信息及镜像详细信息 3
    2.3.2. docker拉取镜像 3
    2.3.3. docker移除(删除)镜像 3
    2.3.4. docker移除未使用的镜像。没有被标记或被任何容器引用的 3
    2.3.5. export导出容器文件系统到tar归档文件 3
    2.3.6. tar保存一个或多个镜像到一个tar归档文件 4
    2.3.7. load加载镜像来自tar归档或标准输入(导入) 4
    2.3.8. docker出现IPv4 forwarding is disabled. Networking will not work解决方法 4
    2.4. 镜像存储核心技术:联合文件系统UFS 4
    2.5. 镜像存储核心技术:写时复制COW 4
  3. Docker容器管理 5
    3.1. 创建容器常用选项 5
    3.1.1. 直接运行一个容器并进入到容器 5
    3.1.2. 后台运行一个容器 5
    3.1.3. 查看最新运行的容器 6
    3.1.4. 查看容器进程 6
    3.1.5. 进入到容器 6
    3.1.6. 容器环境变量-e,-env 6
    3.2. 容器资源限制 6
    3.2.1. 内存限额 6
    3.2.2. CPU限额 7
    3.3. 容器配额扩容 7
    3.3.1. 查看容器资源限额 7
    3.3.2. 更新容器内存限额 7
    3.4. 容器常用命令 7
    3.4.1. 创建容器 7
    3.4.2. 进入容器 8
    3.4.3. 查看容器列表 8
    3.4.4. 查看容器详细信息 8
    3.4.5. 批量强制删除所有容器 8
    3.4.6. 拷贝文件/文件夹到一个容器 8
    3.4.7. 把容器中的文件/文件夹拷贝出来 8
    3.4.8. 以现有的运行容器提交成一个或制作成一个新的镜像 8
    3.4.9. 直接运行容器shell命令 9
    3.5. 容器实现核心技术:Namespace 9
    3.6. 容器实现核心技术:CGroups 9
    3.7. Docker核心组件之间关系 10
  4. Docker 容器数据持久化 11
    4.1. 数据卷(Volume) 11
    4.1.1. 查看数据卷 11
    4.1.2. 创建数据卷 11
    4.1.3. 查看数据卷详细信息 11
    4.1.4. 用数据卷(使用-v参数)创建一个容器 11
    4.1.5. 用数据卷(使用–mount参数)创建容器 12
    4.1.6. 清理数据卷 12
    4.2. 挂载宿主机数据(Bind Mounts) 12
    4.2.1. 将宿主机目录挂载到容器目录(使用-v参数) 12
    4.2.2. 将宿主机目录挂载到容器目录(使用—mount 参数) 12
    4.3. Volume特点 13
    4.4. Bind Mounts特点 13
  5. Docker 容器网络 13
    5.1. 网络模式:bridge详解 14
    5.1.1. 查看当前网络 14
    5.1.2. 查看网络详细信息 14
    5.1.3. 查看网桥 14
    5.1.4. 创建自定义网络 14
    5.1.5. 使用创建的自定义网络 14
    5.2. 网络模式:host、none和container详解 15
    5.2.1. Host 15
    5.2.2. none 16
    5.2.3. container 16
    5.2.4. 重装docker.0虚拟网卡 17
    5.3. Docker网络模型与容器网络访问流程 17
    5.3.1. Docker网络模型 17
    5.3.2. 容器网络访问原理 17
    5.4. 容器网络实现核心技术:Iptables 18
    5.5. 跨主机网络:实现Docker容器多主机通信 19
    5.5.1. 安装etcd 20
    5.5.2. flanneld安装并配置 20
    5.5.3. 向etcd写入子网 20
    5.5.4. 配置Docker使用flannel生成的网络信息 21
    5.5.5. 在两台主机创建容器相互ping验证 21
  6. Dockerfile制作容器镜像 22
    6.1. Dockerfile常用指令及使用 22
    6.2. docker build构建镜像 22
    6.3. CMD与ENTRYPOINT区别 23
    6.3.1. CMD用法 23
    6.3.2. ENTRYPOINT用法 25
    6.3.3. ENTRYPOINT与CMD配合使用,CMD:作为ENTRYPOINT的默认参数 26
    6.4. Docker解决每次进入容器命令都要重新source /etc/profile 才能生效的问题 27
    6.5. 前端项目镜像制作:openresty(nginx) 28
    6.6. 构建Tomcat镜像 31
    6.7. PHP项目镜像制作:PHP5.6 32
  7. docker部署LNMP网站平台 33
  8. Docker 图形化管理 35

1.二进制安装Docker
https://docs.docker.com/
[root@docker ~]#wget https://download.docker.com/linux/static/stable/x86_64/docker-19.03.9.tgz
以下在所有节点操作。这里采用二进制安装,用yum安装也一样。
解压二进制包
[root@docker ~]#tar zxvf docker-19.03.9.tgz
[root@docker ~]#mv docker/* /usr/bin
systemd管理docker
cat > /usr/lib/systemd/system/docker.service << EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF

创建配置文件
[root@docker ~]#mkdir /etc/docker
[root@docker ~]#
cat > /etc/docker/daemon.json << EOF
{
“registry-mirrors”: [“https://b9pmyelo.mirror.aliyuncs.com”]
}
EOF
registry-mirrors 阿里云镜像加速器
启动并设置开机启动
[root@docker ~]#systemctl daemon-reload
[root@docker ~]#systemctl start docker
[root@docker ~]#systemctl enable docker
查看安装docker的相关信息
[root@slave ~]# docker info
2.Docker镜像管理
2.1.镜像是什么
镜像是什么?
• 一个分层存储的文件
• 一个软件的环境
• 一个镜像可以创建N个容器
• 一种标准化的交付
• 一个不包含Linux内核而又精简的Linux操作系统
镜像不是一个单一的文件,而是有多层构成。我们可以通过docker history <ID/NAME> 查看镜像中各层内容及大小,每层
对应着Dockerfile中的一条指令。Docker镜像默认存储在/var/lib/docker/<storage-driver>中。
镜像从哪里来?
Docker Hub是由Docker公司负责维护的公共注册中心,包含大量的容器镜像,Docker工具默认从这个公共镜像库下载镜像。
地址:https://hub.docker.com/explore,可以在上面注册一个账号,并可以上传自定义镜像
2.2.镜像与容器联系
镜像:类似于虚拟机镜像,一个只读模板
容器:通过镜像创建的运行实例
容器其实是在镜像的最上面加了一层读写层,在运行容器里文件改动时,
会先从镜像里要写的文件复制到容器自己的文件系统中(读写层)。
如果容器删除了,最上面的读写层也就删除了,改动也就丢失了。所以无论多
少个容器共享一个镜像,所做的写操作都是从镜像的文件系统中复制过来操作
的,并不会修改镜像的源文件,这种方式提高磁盘利用率。
若想持久化这些改动,可以通过docker commit 将容器保存成一个新镜像。

2.3.管理镜像常用命令
[root@slave ~]# docker image --help
指令 描述
ls 列出镜像
Build 构建镜像来自Dockerfile
history 查看镜像历史
inspect 显示一个或多个镜像详细信息
pull 从镜像仓库拉取镜像
push 推送一个镜像到镜像仓库
rm 移除一个或多个镜像
prune 移除未使用的镜像。没有被标记或被任何容器引用的
tag 创建一个引用源镜像标记目录镜像
export 导出容器文件系统到tar归档文件
import 导入容器文件系统tar归档文件创建镜像
save 保存一个或多个镜像到一个tar归档文件
load 加载镜像来自tar归档或标准输入

2.3.1.docke查看镜像信息及镜像详细信息
[root@slave ~]# docker images
[root@slave ~]# docker inspect nginx
[root@slave ~]# docker inspect 4bb46517cac3
2.3.2.docker拉取镜像
拉取nginx 1.17版本镜像
[root@slave ~]# docker pull nginx:1.17
2.3.3.docker移除(删除)镜像
删除1.17版本nginx 镜像
[root@slave ~]# docker image rm nginx:1.17
强制删除nginx镜像
[root@slave ~]# docker image rm -f nginx
2.3.4.docker移除未使用的镜像。没有被标记或被任何容器引用的
[root@slave ~]# docker image prune
移除所有没有被使用的镜像
[root@slave ~]# docker image prune -a
2.3.5.export导出容器文件系统到tar归档文件
先创建一个容器
[root@slave ~]# docker run -d --name nginx01 nginx
[root@slave ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
944734196e96 nginx “/docker-entrypoint.…” About a minute ago Up About a minute 80/tcp nginx01
[root@slave ~]# docker container export 944734196e96 > nginx.tar
[root@slave ~]# du -sh nginx.tar
下载nginx.tar
[root@slave ~]# sz nginx.tar
2.3.6.tar保存一个或多个镜像到一个tar归档文件
[root@slave ~]# docker images
[root@slave ~]# docker save nginx >nginx.tar
[root@slave ~]# du -sh nginx.tar
2.3.7.load加载镜像来自tar归档或标准输入(导入)
[root@slave ~]# docker load < nginx.tar
[root@slave ~]# docker images

2.3.8.docker出现IPv4 forwarding is disabled. Networking will not work解决方法
1.修改内核参数
vi /etc/sysctl.conf
net.ipv4.ip_forward=0
改成
net.ipv4.ip_forward=1

2.重启network服务
systemctl restart network

3.重启docker服务(这一步最重要,如果没有执行的话,还是会报错的)
systemctl restart docker

4.重启iptables
systemctl restart iptables
2.4.镜像存储核心技术:联合文件系统UFS
镜像怎么高效存储?
难道像虚拟机那样一个容器对应一个独立的镜像文件?这样对于密集型容器,磁盘占用率太大!
答:引入联合文件系统,将镜像多层文件联合挂载到容器文件系统
2.5.镜像存储核心技术:写时复制COW

了解联合文件系统后,我们指定,镜像是只读的,类似共享形式让多个容器使用,如果要在容器里修改文件,即镜像里的文件,那该怎么办呢?
答:引入写时复制(copy-on-write),需要修改文件操作时,会先从镜像里把要写的文件复制到自己的文件系统中进行修改。
3.Docker容器管理
3.1.创建容器常用选项
选项 描述
-i,-interactive 交互式
-t,tty 分配一个伪终端
-d,-detach 运行容器到后台
-e,-env 设置环境变量
-p,-publish list 发布容器端口到主机
-P,-pubilsh-all 发布容器所有EXPOSE的端口到宿主机随机端口
-name string 指定容器名称
-h,-hostname 设置容器主机名
-ip string 指定容器IP,只能用于自定义网络
-network 连接容器到一个网络
-mount mount 将文件系统附加到容器
-v,-volume list 绑定挂载一个卷
-restart string 容器退出时重启策略,默认no,可选值:[always|on-failure]
[root@slave ~]# docker container --help
3.1.1.直接运行一个容器并进入到容器
[root@slave ~]docker run -it centos /bin/bash
3.1.2.后台运行一个容器
[root@slave ~]sudo docker run -itd centos
3.1.3.查看最新运行的容器
[root@slave ~]# docker ps -l
3.1.4.查看容器进程
[root@slave ~]# docker top 176339efeac9

3.1.5.进入到容器
[root@slave ~]# docker container exec -it 176339efeac9 bash
3.1.6.容器环境变量-e,-env

运行一个名为web的容器,并设置容器环境变量test=123456,宿主机的88端口转发容器的80端口,以nginx最新版的镜像来运行!
[root@slave ~]sudo docker container run -d --name web -e test=123456 -p 88:80 -h web nginx
查看最新运行的容器
[root@slave ~]sudo docker ps -l
进入web容器,并查看test变量
[root@slave ~]sudo docker exec -it web bash
root@web:/# echo $test
123456
3.2.容器资源限制
选项
描述
-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共享(相对权重)
3.2.1.内存限额
运行一个容器名为nginx03,允许容器最多使用500M内存和100M的Swap,并禁用OOM Killer,
[root@slave ~]# sudo docker run -itd --name nginx03 --memory=“500m” --memory-swap=“600m” --oom-kill-disable nginx
3.2.2.CPU限额
允许容器最多使用一个半的CPU:
[root@slave ~]# docker run -itd --name nginx04 --cpus=“1.5” nginx
允许容器最多使用50%的CPU:
[root@slave ~]# docker run -d --name nginx05 --cpus=".5" nginx
查看容器资源限制
[root@slave ~]# sudo docker stats --no-stream nginx03
3.3.容器配额扩容
docker update 更新容器配置
[root@slave ~]# docker update --help
运行一个内存限额为512M的容器
[root@slave ~]# docker run -d -m=“512m” nginx
[root@slave ~]# docker ps
3.3.1.查看容器资源限额
[root@slave ~]# docker stats eacfa35556b6
3.3.2.更新容器内存限额
[root@slave ~]# docker update -m=“1024m” eacfa35556b6
[root@slave ~]# docker stats eacfa35556b6
3.4.容器常用命令
选项 描述
ls 列出容器
inspect 查看一个或多个容器详细信息
exec 在运行容器中执行命令
commit 创建一个新镜像来自一个容器
cp 拷贝文件/文件夹到一个容器
logs 获取一个容器的日志
port 列出或指定容器端口映射
top 显示一个容器的运行进程
stats 显示容器资源使用统计
stop/start 停止/启动一个或多个容器
rm 删除一个或多个容器
3.4.1.创建容器
启动一个容器名为web01,以nginx镜像启动的容器
[root@slave ~]# docker run -d --name web01 nginx
[root@slave ~]# docker ps
3.4.2.进入容器
[root@slave ~]# docker exec -it web01 bash
3.4.3.查看容器列表
[root@slave ~]# docker container ls
3.4.4.查看容器详细信息
[root@slave ~]# docker inspect eacfa35556b6
3.4.5.批量强制删除所有容器
[root@slave ~]# docker rm -f $(docker ps -aq)
3.4.6.拷贝文件/文件夹到一个容器
启动一个容器名为web,以nginx镜像启动的容器
[root@slave ~]# docker run -d --name web nginx
将nginx.tar文件拷贝到名为web容器下的/opt目录
[root@slave ~]# docker cp nginx.tar web:/opt
进入容器查看文件
[root@slave ~]# docker exec -it web bash
root@75017d8aa362:/# ls /opt
nginx.tar
3.4.7.把容器中的文件/文件夹拷贝出来
[root@slave ~]# docker cp web:/opt/nginx.tar /tmp
[root@slave ~]# ls /tmp/
nginx.tar

3.4.8.以现有的运行容器提交成一个或制作成一个新的镜像
创建一个用nginx镜像名为web03的容器
[root@slave ~]# docker run -itd --name web03 nginx
以名为web03的容器提交成一个名为web:30的镜像
[root@slave ~]# docker commit web03 web:03
[root@slave ~]# docker images|grep web
3.4.9.直接运行容器shell命令
[root@slave ~]# docker exec web03 ls

3.5.容器实现核心技术:Namespace
在容器化中,一台物理计算机可以运行多个不同操作系统,那就需要解决”隔离性”,彼此感知不到对方存在,有问题互不影响。
Linux内核从2.4.19版本开始引入了namespace概念,其目的是将特定的全局系统资源通过抽象方法使得namespace中进程看起来拥有自己隔离的资源。Docker就是借助这个机制实现了容器资源隔离。
Linux的Namespace机制提供了6种不同的命名空间:
IPC:隔离进程间通信
MOUNT:隔离文件系统挂载点
NET:隔离网络协议栈
PID:隔离进程信号,进程命名空间是一个父子结构,子空间对父空间可见
USER:隔离用户
UTS:隔离主机名和域名

查看命名空间
[root@slave ~]# ll /proc/$$/ns
[root@slave ~]# ls /proc/1/ns

3.6.容器实现核心技术:CGroups
Docker利用namespace实现了容器之间资源隔离,但是namespace不能对容器资源限制,比如CPU、内存。
如果某一个容器属于CPU密集型任务,那么会影响其他容器使用CPU,导致多个容器相互影响并且抢占资源。
如何对多个容器的资源使用进行限制就成了容器化的主要问题。
答:引入Control Groups(简称CGroups),限制容器资源

CGroups: 所有的任务就是运行在系统中的一个进程,而 CGroups 以某种标准将一组进程为目标进行资源分配和控制。
例如CPU、内存、带宽等,并且可以动态配置。
CGroups主要功能:
• 限制进程组使用的资源数量( Resource limitation ):可以为进程组设定资源使用上限,例如内存
• 进程组优先级控制( Prioritization ):可以为进程组分配特定CPU、磁盘IO吞吐量
• 记录进程组使用的资源数量( Accounting ):例如使用记录某个进程组使用的CPU时间
• 进程组控制( Control ):可以将进程组挂起和恢复

ls /sys/fs/cgroup/ -l 查看cgroups可控制的资源:
[root@slave ~]# ls /sys/fs/cgroup/memory/docker/
• blkio :对快设备的IO进行限制。
• cpu:限制CPU时间片的分配,与cpuacct挂载同一目录。
• cpuacct :生成cgroup中的任务占用CPU资源的报告,与cpu挂载同一目录。
• cpuset :给cgroup中的任务分配独立的CPU(多核处理器)和内存节点。 • devices :允许或者拒绝 cgroup 中的任务访问设备。 • freezer :暂停/恢复 cgroup 中的任务。 • hugetlb :限制使用的内存页数量。 • memory :对cgroup 中任务的可用内存进行限制,并自动生成资源占用报告。
• net_cls :使用等级识别符(classid)标记网络数据包,这让 Linux 流量控制程序(tc)可以识别来自特定从cgroup 任务的数据包,并进行网络限制。
• net_prio:允许基于cgroup设置网络流量的优先级。
• perf_event:允许使用perf工具来监控cgroup。 • pids:限制任务的数量。
容器实际资源限制位置:
/sys/fs/cgroup/<资源名>/docker/<容器ID>
3.7.Docker核心组件之间关系
Docker Daemon:Docker守护进程,负责与Docker Clinet交互,并管理镜像、
容器。
Containerd:是一个简单的守护进程,向上给Docker Daemon提供接口,向下
通过containerd-shim结合runC管理容器。
runC:一个命令行工具,它根据OCI标准来创建和运行容器

 Namespace
命名空间,Linux内核提供的一种对进程资源隔离的机制,例如进程、网络、挂载点等资源。
 CGroups
控制组,Linux内核提供的一种对进程组限制资源的机制;例如CPU、内存等资源。
 UnionFS
联合文件系统,支持将不同位置的目录挂载到同一虚拟文件系统,形成一种分层的模型。

4.Docker 容器数据持久化
Docker提供三种方式将数据从宿主机挂载到容器中:
• volumes:Docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)。保存数据的最佳方式。
• bind mounts:将宿主机上的任意位置的文件或者目录挂载到容器中。
• tmpfs:挂载存储在主机系统的内存中,而不会写入主机的文件系统。如果不希望将数据持久存储在任何位置,可以使用
tmpfs,同时避免写入容器可写层提高性能。
4.1.数据卷(Volume)
volumes:Docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)。保存数据的最佳方式
[root@slave ~]# docker volume --help
4.1.1.查看数据卷
[root@slave ~]# docker volume ls
4.1.2.创建数据卷
创建名为ginx-vol 数据卷
[root@slave ~]# docker volume create nginx-vol
[root@slave ~]# docker volume ls
4.1.3.查看数据卷详细信息
[root@slave ~]# docker volume inspect nginx-vol

4.1.4.用数据卷(使用-v参数)创建一个容器
创建一个以nginx镜像名为nginx-test的容器,并将容器的/usr/share/nginx/html挂载到nginx-vol数据卷中
[root@slave ~]# docker run -d --name=nginx-test -v nginx-vol:/usr/share/nginx/html nginx
[root@slave ~]# docker volume inspect nginx-vol
[root@slave ~]# ls /var/lib/docker/volumes/nginx-vol/_data/
访问以Nginx镜像创建的容器
查看容器详细信息,查看容器IP
[root@slave ~]# docker inspect 8edbe659f4af
[root@slave ~]# curl 172.17.0.3
看到可以访问到nginx首页
删除容器后,查看数据还存在
[root@slave ~]#docker stop nginx-test
[root@slave ~]# docker rm nginx-test
[root@slave ~]# ls /var/lib/docker/volumes/nginx-vol/_data/
50x.html index.html
4.1.5.用数据卷(使用–mount参数)创建容器
创建一个以nginx镜像名为nginx-test的容器,并将容器的/usr/share/nginx/html挂载到nginx-vol数据卷中,src 数据卷名称,dst 容器目标目录
[root@slave ~]# docker run -d --name=nginx-test --mount src=nginx-vol,dst=/usr/share/nginx/html nginx
4.1.6.清理数据卷
[root@slave ~]#docker stop nginx-test
[root@slave ~]# docker rm nginx-test
[root@slave ~]# docker volume rm nginx-vol
注意:

  1. 如果没有指定卷,自动创建。
  2. 建议使用–mount,更通用。
    4.2.挂载宿主机数据(Bind Mounts)
    bind mounts:将宿主机上的任意位置的文件或者目录挂载到容器中
    4.2.1.将宿主机目录挂载到容器目录(使用-v参数)
    以nginx镜像后台运行一个名为nginx-test的容器,将宿主机/usr/local/nginx/挂载到容器/usr/share/nginx/html下
    [root@slave ~]# docker run -itd --name=nginx-test -v /usr/local/nginx/:/usr/share/nginx/html nginx
    注意:宿主机没有/usr/local/nginx/目录,执行上述命令,会自动在宿主机上创建/usr/local/nginx/目录
    [root@slave ~]# ls /usr/local/nginx/
    验证绑定
    写入数据文件到/usr/local/nginx/中,然后获取创建容器IP,再进行访问
    [root@slave ~]# echo hello > /usr/local/nginx/index.html
    [root@slave ~]# docker inspect nginx-test
    [root@slave ~]# curl 172.17.0.2
    Hello

4.2.2.将宿主机目录挂载到容器目录(使用—mount 参数)
[root@slave ~]# mkdir /usr/local/nginx
以nginx镜像后台运行一个名为nginx-test的容器,type bind,src宿主机目录/usr/local/nginx/,容器目录/usr/share/nginx/html
[root@slave ~]# docker run -itd --name=nginx-test --mount type=bind,src=/usr/local/nginx/,dst=/usr/share/nginx/html nginx
验证绑定
写入数据文件到/usr/local/nginx/中,然后获取创建容器IP,再进行访问
[root@slave ~]# echo hello > /usr/local/nginx/index.html
[root@slave ~]# docker inspect nginx-test
[root@slave ~]# curl 172.17.0.2
清理
[root@slave ~]# docker stop nginx-test
[root@slave ~]# docker rm nginx-test
注意:

  1. 如果挂载目标在容器中非空目录,则该目录现有内容将被隐藏。

4.3.Volume特点
• 多个运行容器之间共享数据。
• 当容器停止或被移除时,该卷依然存在。
• 多个容器可以同时挂载相同的卷。
• 当明确删除卷时,卷才会被删除。
• 将容器的数据存储在远程主机或其他存储上
• 将数据从一台Docker主机迁移到另一台时,先停止容器,然后备份卷的目录(/var/lib/docker/volumes/)
4.4.Bind Mounts特点
• 从主机共享配置文件到容器。默认情况下,挂载主机/etc/resolv.conf到每个容器,提供DNS解析。
• 在Docker主机上的开发环境和容器之间共享源代码。例如,可以将Maven target目录挂载到容器中,每次在Docker主机
上构建Maven项目时,容器都可以访问构建的项目包。

5.Docker 容器网络
四种网络模式
• bridge
–net=bridge
默认网络,Docker启动后创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。
• host
–net=host
容器不会获得一个独立的network namespace,而是与宿主机共用一个。这就意味着容器不会有自己的网卡信息,而是使用宿主
机的。容器除了网络,其他都是隔离的。
• none
–net=none
获取独立的network namespace,但不为容器进行任何网络配置,需要我们手动配置。
• container
–net=container:Name/ID
与指定的容器使用同一个network namespace,具有同样的网络配置信息,两个容器除了网络,其他都还是隔离的。
5.1.网络模式:bridge详解
bridge
–net=bridge
默认网络,Docker启动后创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。
[root@slave ~]# ip a |grep docker
可以看到一个docker0网桥
[root@slave ~]# docker network --help
5.1.1.查看当前网络
[root@slave ~]# docker network ls
5.1.2.查看网络详细信息
[root@slave ~]# docker network inspect 32a604c8eddf
5.1.3.查看网桥
[root@slave ~]# yum install bridge-utils -y
[root@slave ~]# brctl show docker0
5.1.4.创建自定义网络
[root@slave ~]# docker network create test
如果创建网络报错,重启iptables和docker
[root@slave ~]# systemctl restart iptables
[root@slave ~]# systemctl restart docker
[root@slave ~]# docker network ls
5.1.5.使用创建的自定义网络
与默认的bridge原理一样,但自定义网络具备内部DNS发现,可以通过容器名或者主机名容器之间网络通信
用Nginx镜像创建一个名为nginx-test的容器并加入自定义的网络test中
[root@slave ~]# docker run -itd --name=nginx-test --network test nginx
[root@slave ~]# docker ps
5.1.5.1.查看创建容器分配的IP
[root@slave ~]# docker inspect nginx-test|grep IPAddress
5.1.5.2.测试容器使用自定义的网络
1.用busybox镜像,后台运行一个名为bs1的容器,容器网络加入到名为test网络当中
[root@slave ~]# sudo docker run -itd --name=bs1 --network test busybox
2.用busybox镜像,后台运行一个名为bs2的容器,容器网络加入到名为test网络当中
[root@slave ~]# sudo docker run -itd --name=bs2 --network test busybox
3.进入bs1或bs2,然后ping 名字为bs1或bs1的容器或主机名,可以发现能够ping通bs1或bs2
[root@slave ~]# docker exec -it bs1 sh
/ # ping bs2
PING bs2 (172.18.0.4): 56 data bytes
64 bytes from 172.18.0.4: seq=0 ttl=64 time=0.125 ms
64 bytes from 172.18.0.4: seq=1 ttl=64 time=0.102 ms

5.2.网络模式:host、none和container详解
• host
–net=host
容器不会获得一个独立的network namespace,而是与宿主机共用一个。这就意味着容器不会有自己的网卡信息,而是使用宿主机的。容器除了网络,其他都是隔离的。
• none
–net=none
获取独立的network namespace,但不为容器进行任何网络配置,需要我们手动配置。
• container
–net=container:Name/ID
与指定的容器使用同一个network namespace,具有同样的网络配置信息,两个容器除了网络,其他都还是隔离的。
5.2.1.Host
–net=host
容器不会获得一个独立的network namespace,而是与宿主机共用一个。这就意味着容器不会有自己的网卡信息,而是使用宿主机的。容器除了网络,其他都是隔离的。
运行两个容器,一个加–net=host,一个不加–net=host,然后分别进入容器查看网卡,可以看到加了–net=host的容器有很多网卡,网络协议都是来自宿主机;没有加–net=host的网卡很少
用busybox镜像运行一个名为host1的容器,net类型为host
[root@slave ~]# docker run -itd --name=host1 --net=host busybox
用busybox镜像运行一个名为host2的容器
[root@slave ~]# docker run -itd --name=host2 busybox
[root@slave ~]# docker exec -it host1 sh
/ # ifconfig
[root@slave ~]# docker exec -it host2 sh
/ # ifconfig
5.2.1.1.查看宿主机监听的端口
[root@slave ~]# ss -antp
5.2.1.2.使用–net=host模式查看运行的容器占用宿主机端口
用nginx镜像运行一个名为host3,–net模式为host的容器
[root@slave ~]# docker run -itd --name=host3 --net=host nginx
[root@slave ~]# ss -antp|grep 80
[root@slave ~]# netstat -tulnp |grep 80
可以看到宿主机的80端口被占用
5.2.2.none
–net=none
获取独立的network namespace,但不为容器进行任何网络配置,需要我们手动配置。
用busybox镜像运行一个名为none,–net模式为none的容器
[root@slave ~]# docker run -itd --name=none --net=none busybox
进入容器
[root@slave ~]# docker exec -it none sh
/ # ifconfig
发现没有网卡信息

5.2.3.container
–net=container:Name/ID
与指定的容器使用同一个network namespace,具有同样的网络配置信息,两个容器除了网络,其他都还是隔离的。
用busybox镜像创建一个名为container1的容器
[root@slave ~]# docker run -itd --name=container1 busybox
用busybox镜像创建一个名为container2,并加入到container1的网络命名空间
[root@slave ~]# docker run -itd --name=container2 --net=container:container1 busybox
分别进入到容器container1和container2
[root@slave ~]# docker exec -it container1 sh
/ # ifconfig
[root@slave ~]# docker exec -it container2 sh
/ # ifconfig
发现两个IP地址一样
5.2.4.重装docker.0虚拟网卡
安装工具
[root@docekr ~]# yum install bridge-utils -y
[root@docekr ~]# systemctl stop docker
[root@docekr ~]# ip link set dev docker0 down
[root@docekr ~]# brctl delbr docker0
然后重启docker
[root@docekr ~]# systemctl restart docker
即可发现自动生成个docker0网桥
5.3.Docker网络模型与容器网络访问流程
5.3.1.Docker网络模型
veth pair:成对出现的一种虚拟网络设备,数据从一端进,从另一端出。 用于解决网络命名空间之间隔离。
docker0:网桥是一个二层网络设备,通过网桥可以将Linux支持的不同的端口连接起来,并实现类似交换机那样的多对多的通信。

5.3.2.容器网络访问原理

容器内: route是路由表的意思
首先由容器内部的 eth0(也就是veth1),发送给容器的网关 route里的 eth0(也就是宿主机的网卡 veth0)

容器外:
自定义网络的话,就会创建 一个linux网桥(br-5c710e739634),172.18.0.1 就是网关 。这个br-5c710e739634 整体就是宿主机的一个虚拟网卡。
接收 ↑发送过来的数据

5.4.容器网络实现核心技术:Iptables
表 链
filter(过滤) INPUT、OUTPUT、FORWARD
nat(地址转换) PREROUTING、POSTROUTING、OUTPUT
mangle(拆包、修改、封装) INPUT、OUTPUT、PREROUTING、POSTROUTING、OUTPUT
raw(数据状态跟踪) PREROUTING、OUTPUT
四表五链

iptables table Command Chain Parameter & Xmatch target
-t filter
nat -A
-D
-L
-F
-P
-I
-R
-n INPUT
FORWARD
OUTPUT
PREROUTING
POSTROUTING -p tcp
-s
-d
–sport
–dport
–dports
-m tcp
state
multiport -j ACCEPT
DROP
REJECT
DNAT
SNAT
操作命令

INPUT链:接收的数据包是本机(入站)时,应用此链中的规则。
OUTPUT链:本机向外发送数据包(出站)时,应用此链中的规则。
FORWARD链:需要通过防火墙中转发送给其他地址的数据包(转发)时,应用测链中的规则。
PREROUTING链:在对数据包做路由选择之前,应用此链中的规则。DNAT
POSTROUTING链:在对数据包做路由选择之后,应用此链中的规则。SNAT

查看所有iptables规则
[root@slave ~]# iptables -vnL
[root@slave ~]# iptables-save

外部访问容器
[root@slave ~]# iptables -t nat -vnL DOCKER

容器访问外部
[root@slave ~]# iptables -t nat -vnL POSTROUTING

5.5.跨主机网络:实现Docker容器多主机通信
Flannel是CoreOS维护的一个网络组件,在每个主机上运行守护进程负责维护本地路由转发,Flannel使用ETCD来存储容器网络与主机之前的关系。
其他主流容器跨主机网络方案:
• Weave
• Calico
• OpenvSwitch

主机1 内网IP:10.170.0.26 公网IP:35.220.238.143
主机2 内网IP:10.170.0.25 公网IP:35.220.197.26

5.5.1.安装etcd
在其中一台机器安装部署即可
[root@docker ~]# yum install etcd -y
[root@docker ~]# vim /etc/etcd/etcd.conf
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS=“http://10.170.0.25:2379”
ETCD_NAME=“default”
ETCD_ADVERTISE_CLIENT_URLS=“http://10.170.0.25:2379”
[root@docker ~]# systemctl start etcd
[root@docker ~]# systemctl enable etcd
[root@docker ~]# ps -ef |grep etcd
[root@docker ~]# netstat -nutlp|grep etcd
5.5.2.flanneld安装并配置
在所有docker主机部署
[root@slave ~]#yum install flannel -y
[root@docker ~]# vim /etc/sysconfig/flanneld

FLANNEL_ETCD_ENDPOINTS=“http://10.170.0.25:2379”
FLANNEL_ETCD_PREFIX="/atomic.io/network"
5.5.3.向etcd写入子网
[root@docker ~]#etcdctl --endpoints=“http://10.170.0.25:2379” set /atomic.io/network/config ‘{ “Network”: “172.17.0.0/16”,“Backend”: {“Type”: “vxlan”} }’
获取值
[root@docker ~]#etcdctl --endpoints=“http://10.170.0.25:2379” get /atomic.io/network/config ‘{“Network”:“172.0.0.0/16”,“Backend”:{“Type”:“vxlan”}}’

启动flanneld并查看日志
[root@docker ~]# systemctl start flanneld
[root@docker ~]# tail -f /var/log/messages

5.5.4.配置Docker使用flannel生成的网络信息
[root@docker ~]# cat /run/flannel/docker
[root@docker ~]# vim /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
EnvironmentFile=/run/flannel/docker
Type=notify
ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS
ExecReload=/bin/kill -s HUP
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
[root@docker ~]# systemctl daemon-reload
[root@docker ~]# systemctl restart docker
[root@docker ~]# ps -ef |grep docker|grep bip
可以看到引用到了/run/flannel/docker里的配置文件
5.5.5.在两台主机创建容器相互ping验证
两台主机开启iptables FORWARD
[root@docekr ~]# iptables -vnL|grep FORWARD
[root@docekr ~]# iptables -P FORWARD ACCEPT
然后先重启flanneld,再重启docker
[root@slave ~]# systemctl restart flanneld
[root@slave ~]# systemctl restart docker
再在两台主机上运行容器相互ping验证
[root@slave ~]# docker run -itd --name=slave busybox
[root@docekr ~]# docker run -itd --name=docker busybox
[root@slave ~]# docker exec -it slave sh
/ # ping 172.17.46.2
6.Dockerfile制作容器镜像
6.1.Dockerfile常用指令及使用
指令 描述
FROM 构建新镜像是基于哪个镜像
LABEL 标签
RUN 构建镜像时运行的Shell命令
COPY 拷贝文件或目录到镜像中
ADD 解压压缩包并拷贝
ENV 设置环境变量
USER 为RUN、CMD、ENTRYPOINT执行命令指定运行用户
EXPOSE 声明容器运行的服务端口
WORKDIR 为RUN、CMD、ENTRYPOINT、COPY和ADD设置工作目录
CMD 运行容器时默认执行,如果有多个CMD指令,最后一个生效
ENTRYPOINT 如果与CMD一起用,CMD将作为ENTRYPOINT的默认参数,如果有多个ENTRYPOINT指令,最后一个生效

6.2.docker build构建镜像
创建一个空目录
[root@slave ~]# mkdir build
[root@slave ~]# cd build
[root@slave build]# touch a.txt
[root@slave build]# touch b.txt
[root@slave build]# tar zcvf b.tar.gz b.txt
[root@slave build]# vim Dockerfile
FROM centos:7
LABEL maintainer wenjusir
RUN yum install wget curl -y
COPY a.txt /opt
ADD b.tar.gz /opt
ENV ABC=123
EXPOSE 80
WORKDIR /usr/local
CMD [“sleep”,“36000”]

Usage: docker build [OPTIONS] PATH | URL | - [flags]
Options:
-t, --tag list # 镜像名称
-f, --file string # 指定Dockerfile文件位置

指定Dockerfile文件(-f),创建名为test的镜像,.表示有拷贝文件的路径
[root@slave build]# docker build -t test -f Dockerfile .
[root@slave build]# docker images
可以看到构建的test镜像
用创建的test镜像启动一个名为test1的容器
[root@slave build]# docker run -itd --name=test1 test
进入容器
[root@slave build]# docker exec -it test1 bash
验证构建的变量值
[root@947758378ba5 local]# echo $ABC
123
验证解压和拷贝的文件
[root@947758378ba5 local]# ls /opt/
a.txt b.txt

6.3.CMD与ENTRYPOINT区别
CMD用法:
• CMD [“executable”,“param1”,“param2”] :exec形式(首选)
• CMD [“param1”,“param2”] :作为ENTRYPOINT的默认参数
• CMD command param1 param2 :Shell形式

6.3.1.CMD用法
6.3.1.1.CMD exec形式
[root@slave build]# vim run.sh
#!/bin/bash
echo hello $1
sleep 60000
[root@slave build]# chmod +x run.sh
[root@slave build]# vim Dockerfile_CMD
FROM centos:7
LABEL maintainer wenjusir
COPY run.sh /usr/bin
EXPOSE 80
CMD [“run.sh”,“wenju”]
开始构建指定文件Dockerfile_CMD,构建后的镜像名称为cmd_01
[root@slave build]# docker build -t cmd_01 -f Dockerfile_CMD .
[root@slave build]# docker images|grep cmd
用新构建的cmd_01镜像运行一个名为cmd的容器
[root@slave build]# docker run -itd --name=cmd cmd_01
查看运行的cmd容器日志,看到输出内容为 hello wenju,说明用构建的镜像运行的容器,默认运行run.sh脚本
[root@slave build]# docker logs cmd
hello wenju

注意:使用exec默认CMD命令不支持传变量
类似以下标红的地方不支持
[root@slave build]# vim Dockerfile_CMD
FROM centos:7
LABEL maintainer wenjusir
COPY run.sh /usr/bin
ENV NAME=wenju
EXPOSE 80
CMD [“run.sh”,"$NAME"]
指定Dockerfile_CMD 文件构建名为test_cmd镜像
[root@slave build]# docker build -t test_cmd -f Dockerfile_CMD .
用构建的testcmd 镜像运行一个名为testcmd的容器
[root@slave build]# docker run -itd --name testcmd test_cmd
[root@slave build]# docker logs testcmd
hello $NAME
可以看到以上输出的内容没有解析到变量值,要想解析变量值,可以指定运行shell脚本
如下
[root@slave build]# vim Dockerfile_CMD
FROM centos:7
LABEL maintainer wenjusir
COPY run.sh /usr/bin
ENV NAME=wenju
EXPOSE 80
CMD [“sh”,"-c","/usr/bin/run.sh $NAME"]
指定Dockerfile_CMD 文件构建名为test_cmd1镜像
[root@slave build]# docker build -t test_cmd1 -f Dockerfile_CMD .
用构建的testcmd1 镜像运行一个名为testcmd1的容器
[root@slave build]# docker run -itd --name testcmd1 test_cmd1
[root@slave build]# docker logs testcmd1
hello wenju
6.3.1.2.Shell形式
直接调用shell脚本,支持传变量
[root@slave build]# vim Dockerfile_CMD
FROM centos:7
LABEL maintainer wenjusir
COPY run.sh /usr/bin
ENV NAME=wenjusir
EXPOSE 80
CMD /usr/bin/run.sh $NAME
指定Dockerfile_CMD 文件构建名为test_cmd2镜像
[root@slave build]# docker build -t test_cmd2 -f Dockerfile_CMD .
用构建的testcmd2 镜像运行一个名为testcmd2的容器
[root@slave build]# docker run -itd --name testcmd2 test_cmd2
[root@slave build]# docker logs testcmd2
hello wenjusir
6.3.1.3.覆盖默认构建的镜像CMD命令
用构建的test_cmd2 镜像运行一个名为test_fugai的容器,并直接运行run.sh脚本赋值参数sunwenju
[root@slave build]# docker run -itd --name=test_fugai test_cmd2 run.sh sunwenju
[root@slave build]# docker logs test_fugai
hello sunwenju
可以看到打印出的值是sunwenju,并不是wenjusir
6.3.2.ENTRYPOINT用法
• ENTRYPOINT [“executable”, “param1”, “param2”]
• ENTRYPOINT command param1 param2

[root@slave build]# vim Dockerfile_ENT
FROM centos:7
LABEL maintainer wenjusir
COPY run.sh /usr/bin
ENV NAME=wenjusir
EXPOSE 80
ENTRYPOINT /usr/bin/run.sh $NAME
用Dockerfile_ENT文件构建一个名为test_ent镜像
[root@slave build]# docker build -t test_ent -f Dockerfile_ENT .
用构建的test_ens镜像运行一个名为ens的容器
[root@slave build]# docker run -itd --name=ens test_ent
[root@slave build]# docker logs ens
hello wenjusir

注意:ENTRYPOINT不能覆盖默认运行的命令
用构建的test_ent镜像运行一个名为test_ent的容器,并直接运行run.sh脚本赋值参数sunwenju

[root@slave ~]# docker run -itd --name=test_ent test_ent run.sh aju
[root@slave ~]# docker logs test_ent
hello wenjusir
发现还是输出wenjusir变量
6.3.3.ENTRYPOINT与CMD配合使用,CMD:作为ENTRYPOINT的默认参数
[root@slave build]# vim Dockerfile_ENT_CMD
FROM centos:7
LABEL maintainer wenjusir
COPY run.sh /usr/bin/
ENV NAME=wenjusun
EXPOSE 80
ENTRYPOINT [“echo”]
CMD [“hello”,“wenju”]
用Dockerfile_ENT_CMD构建一个名为test_ent_cmd的镜像
[root@slave build]# docker build -t test_ent_cmd -f Dockerfile_ENT_CMD .
用构建的test_ent_cmd镜像启动一个名为ent_cmd的容器
[root@slave build]# docker run -itd --name=ent_cmd test_ent_cmd
[root@slave build]# docker logs ent_cmd
hello wenju
直接输出hello wenju

[root@slave build]# vim run.sh
#!/bin/bash
echo $@
sleep 60000
[root@slave build]# vim Dockerfile_ENT_CMD
FROM centos:7
LABEL maintainer wenjusir
COPY run.sh /usr/bin/
ENV NAME=wenjusun
EXPOSE 80
ENTRYPOINT [“run.sh”]
CMD [“hello”,“wenju”]
用Dockerfile_ENT_CMD构建一个名为test_ent_cmd1的镜像
[root@slave build]# docker build -t test_ent_cmd1 -f Dockerfile_ENT_CMD .
用构建的test_ent_cmd1镜像启动一个名为ent_cmd1的容器
[root@slave build]# docker run -itd --name=ent_cmd1 test_ent_cmd1
[root@slave build]# docker logs ent_cmd1
hello wenju
还是直接输出hello wenju

注意:这种情况下(exec形式下[“run.sh”])可以覆盖默认的CMD
用构建的test_ent_cmd1镜像运行一个名为ent_cmd_fugai的容器,并赋值hello world
[root@slave build]# docker run -itd --name=ent_cmd_fugai test_ent_cmd1 hello world
[root@slave build]# docker logs ent_cmd_fugai
hello world
可以看到输出的内容为赋予的hello world值
非exec形式下()不支持覆盖CMD
[root@slave build]# vim Dockerfile_ENT_CMD
FROM centos:7
LABEL maintainer wenjusir
COPY run.sh /usr/bin/
ENV NAME=wenjusun
EXPOSE 80
ENTRYPOINT “run.sh”
CMD [“hello”,“wenju”]
用Dockerfile_ENT_CMD构建一个名为test_ent_cmd2的镜像
[root@slave build]# docker build -t test_ent_cmd2 -f Dockerfile_ENT_CMD .
用构建的test_ent_cmd2镜像运行一个名为ent_cmd_fugai2的容器,并赋值hello world
[root@slave build]# docker run -itd --name=ent_cmd_fugai2 test_ent_cmd2 hello wenju
[root@slave build]# docker logs ent_cmd_fugai2
可以看到输出为空

小结:

  1. CMD和ENTRYPOINT指令都可以用来定义运行容器时所使用的默认命令
  2. Dockerfile至少指定一个CMD或ENTRYPOINT
  3. CMD可以用作ENTRYPOINT默认参数,或者用作容器的默认命令
  4. docker run指定时,将会覆盖CMD
  5. 如果是可执行文件,希望运行时传参,应该使用ENTRYPOINT

6.4.Docker解决每次进入容器命令都要重新source /etc/profile 才能生效的问题
在~/.bashrc里面加一句source /etc/profile
[root@606b87b58111 /]# cd
[root@606b87b58111 ~]# vim ~/.bashrc

.bashrc

User specific aliases and functions

alias rm=‘rm -i’
alias cp=‘cp -i’
alias mv=‘mv -i’

Source global definitions

if [ -f /etc/bashrc ]; then
. /etc/bashrc
source /etc/profile
fi

6.5.前端项目镜像制作:openresty(nginx)
[root@slave ~]# mkdir buildfiles
[root@slave ~]# cd buildfiles
编辑配置nginx的基础配置文件
[root@slave ~]# vim nginx.conf
worker_processes 2;
worker_rlimit_nofile 102400;
worker_cpu_affinity 0000001;
pid /usr/local/openresty/nginx/logs/nginx.pid;
events {
use epoll;
worker_connections 1024;
}
http {
lua_shared_dict limit 50m;
lua_package_path “/usr/local/openresty/nginx/conf/waf/?.lua”;
init_by_lua_file “/usr/local/openresty/nginx/conf/waf/init.lua”;
access_by_lua_file “/usr/local/openresty/nginx/conf/waf/access.lua”;
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
log_format main '$remote_addr - r e m o t e u s e r [ remote_user [ remoteuser[time_local] “KaTeX parse error: Double superscript at position 34: … '̲status b o d y b y t e s s e n t " body_bytes_sent " bodybytessent"http_referer” ’
‘“ h t t p u s e r a g e n t " " http_user_agent" " httpuseragent""http_x_forwarded_for”’;

access_log  logs/access.log  main;
tcp_nopush     on;
autoindex off;
server_tokens off;
gzip  on;
gzip_buffers 4 16k;
gzip_comp_level 2;
gzip_min_length 1k;
gzip_http_version 1.0;
gzip_types text/plain application/html application/css application/javascript application/xml;
gzip_vary on;
client_max_body_size 8m;

include     vhosts/*.conf;

}
[root@slave buildfiles]# vim wenjusir.conf
upstream tomcat{
server 127.0.0.1:8080;
}
upstream php{
server 127.0.0.1:9000;
}
server {
listen 80;
server_name localhost;
access_log logs/osce.access.log main;
location / {
#rewrite ^ https:/ h t t p h o s t http_host httphostrequest_uri? permanent;
root html;
index index.html index.htm index.php;
proxy_redirect off;
#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto KaTeX parse error: Expected 'EOF', got '#' at position 52: …ize 10m; #̲允许客户端请求的最大单文件字节… {
#proxy_pass http://tomcat;
root html;
expires 15d;
index index.html index.htm;
}

  location ~ \.jsp(.*)$ {
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
    	proxy_set_header REMOTE-HOST $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_pass http://tomcat;
}
     location ~ \.php(.*)$ {
               root        html;
               fastcgi_pass   127.0.0.1:9000;
               fastcgi_index  index.php;
               fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
               fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
               fastcgi_param  PATH_INFO  $fastcgi_path_info;
               fastcgi_param  PATH_TRANSLATED  
               $document_root$fastcgi_path_info;
               include        fastcgi_params;
    }
  }

[root@slave buildfiles]# vim Dockerfile-openresty
FROM centos:7
MAINTAINER sunwenju
RUN yum install -y gcc wget gcc-c++ make
openssl-devel pcre-devel gd-devel
iproute net-tools telnet wget curl unzip perl kernel-headers kernel-devel vim &&
yum clean all &&
rm -rf /var/cache/yum/*
RUN yum -y install gcc make pcre pcre-devel zlib zlib-devel openssl-devel readline-devel &&
cd &&
wget https://openresty.org/download/openresty-1.15.8.1.tar.gz &&
tar zxf openresty-1.15.8.1.tar.gz &&
cd openresty-1.15.8.1 &&
./configure --prefix=/usr/local/openresty
–with-http_stub_status_module
–with-http_ssl_module
–with-stream &&
make -j 2 && make install &&
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&
cd &&
wget https://github.com/unixhot/waf/archive/v1.0.0.tar.gz &&
tar zxf v1.0.0.tar.gz &&
cp -r waf-1.0.0/waf /usr/local/openresty/nginx/conf/

ENV PATH $PATH:/usr/local/openresty/nginx/sbin
COPY nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
WORKDIR /usr/local/openresty/nginx
EXPOSE 80 443
CMD [“nginx”, “-g”, “daemon off;”]
以Dockerfile构建一个名为openresty,版本v1的镜像,.表示上下文的目录,比如代码中有COPY复制文件到镜像中,.就表示需要复制文件所在的路径
用Dockerfile-openresty文件构建一个名为openresty:wenjusir镜像
[root@slave buildfiles]sudo docker build -t openresty:wenjusir -f Dockerfile-openresty .
用构建的openresty:wenjusir镜像创建一个名为openresty_wenjusir,并暴露容器80端口,用宿主机的80端口转发
[root@slave buildfiles]# docker run -itd --name=openresty_wenjusir -p80:80 openresty:wenjusir
[root@slave buildfiles]# docker exec -it openresty_wenjusir bash
访问宿主机80端口

也可以将宿主机的目录挂载到容器的相应目录下(数据持久化)
用构建的openresty:wenjusir的镜像运行一个名为aju的容器,并将宿主机的root目录g挂载到容器的目录下
[root@slave buildfiles]# docker run -itd --name=aju -v /root:/root -p 80:80 openresty:wenjusir
进入容器后,可以发现容器root目录下有宿主机root目录下的文件
[root@slave buildfiles]# docker exec -it aju bash
[root@4afc0bb73f4a nginx]# ls /root
boost_1_59_0.tar.gz docker-19.03.9.tgz nginx.tar

6.6.构建Tomcat镜像

[root@slave ~]# mkdir build_tomcat/
[root@slave ~]# cd build_tomcat/
[root@slave build_tomcat]# vim Dockerfile_tomcat
FROM centos:7
MAINTAINER sunwenju

RUN yum install -y gcc wget gcc-c++ make
openssl-devel pcre-devel gd-devel
iproute net-tools telnet wget curl unzip perl kernel-headers kernel-devel vim &&
yum clean all &&
rm -rf /var/cache/yum/* &&
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY jdk-8u45-linux-x64.tar.gz /root
RUN cd /root &&
tar zxf jdk-8u45-linux-x64.tar.gz &&
mv jdk1.8.0_45 /usr/local/jdk1.8
COPY apache-tomcat-8.5.31.tar.gz /root
RUN cd /root &&
tar zxf apache-tomcat-8.5.31.tar.gz &&
mv apache-tomcat-8.5.31 /usr/local/tomcat
ENV JAVA_HOME=/usr/local/jdk1.8
ENV JRE_HOME= J A V A H O M E / j r e E N V C L A S S P A T H = . : JAVA_HOME/jre ENV CLASSPATH=.: JAVAHOME/jreENVCLASSPATH=.:JAVA_HOME/lib/dt.jar: J A V A H O M E / l i b / t o o l s . j a r : JAVA_HOME/lib/tools.jar: JAVAHOME/lib/tools.jar:JRE_HOME/lib: C L A S S P A T H E N V P A T H = / s b i n : CLASSPATH ENV PATH=/sbin: CLASSPATHENVPATH=/sbin:JAVA_HOME/bin:$PATH

WORKDIR /usr/local/tomcat
EXPOSE 8080
CMD ["/usr/local/tomcat/bin/catalina.sh", “run”]
用Dockerfile文件构建名为tomcat:wenjusir镜像
[root@slave build_tomcat]# docker build -t tomcat:wenjusir -f Dockerfile_tomcat .
用构建的tomcat:wenjusir镜像运行一个名为tomcat容器,并用宿主机的8080端口转发容器的8080端口
[root@slave build_tomcat]# docker run -itd --name=tomcat -p 8080:8080 tomcat:wenjusir
进入容器查看
[root@slave build_tomcat]# docker exec -it tomcat bash
[root@70174b072a5f tomcat]# netstat -ntulp

6.7.PHP项目镜像制作:PHP5.6
[root@slave ~]# mkdir build_php
[root@slave ~]# cd build_php/
[root@slave build_php]# vim Dockerfile_php
FROM centos:7
MAINTAINER www.ctnrs.com
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/*

ADD php-5.6.36.tar.gz /
RUN 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
COPY php.ini /usr/local/php/etc/
COPY php-fpm.conf /usr/local/php/etc/
WORKDIR /usr/local/php
EXPOSE 9000
CMD [“php-fpm”]

用Dockerfile_php构建php镜像,版本5.6.36; .表示上下文的目录,比如代码中有COPY复制文件到镜像中,.就表示需要复制文件所在的路径
#sudo docker build -t php:5.6.36 -f Dockerfile_php .
验证创建的PHP镜像是否有效

sudo docker run -d --name php01 php:5.6.36

#sudo docker ps -l
#sudo docker exec -it php01 bash
#[root@2821416d7282 php]# netstat -ntulp
7.docker部署LNMP网站平台
注意:这里php和mysql可以不用对外进行端口映射,只需要对外提供一个nginx流量入口
7.1.自定义网络
#sudo docker network create lnmp
7.2.创建Mysql容器
以镜像mysql:5.7,后台运行一个名为lnmp_mysql的容器,–mount方式挂载数据盘到容器中/var/lib/mysql目录,mysql的root用户名密码是123456,默认创建一个wordpress数据库,字符集是utf8
#sudo 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
7.3.查看宿主机docker数据卷
#sudo ls /var/lib/docker/volumes/mysql-vol/_data
7.4.创建PHP容器
用构建的php:v1镜像,运行一个名为lnmp_php的容器,容器加入lnmp网络,挂载方式mount,创建数据卷wwwroot,挂载到容器/wwwroot目录下
#docker run -d --name lnmp_php --net lnmp --mount src=wwwroot,dst=/wwwroot php:v1
创建一个nginx主配置文件
文件内容
user nobody;
worker_processes 4;
worker_rlimit_nofile 65535;

error_log logs/error.log notice;

pid /var/run/nginx.pid;

events {
use epoll;
worker_connections 4096;
}

http {

include       mime.types;
default_type  application/octet-stream;

log_format  main '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

access_log off;
keepalive_timeout  65;

client_max_body_size         64m;
server {
    listen 80;
    server_name www.ctnrs.com;
    index index.php index.html;

    access_log logs/www.ctnrs.com_access.log;
    error_log logs/www.ctnrs.com_error.log;

    # location ~ .*\.(js|css|html|png|gif|jpg|jpeg)$ {
    location / {
        root /wwwroot;
    }

    location ~* \.php$ {
        root /wwwroot;
        fastcgi_pass lnmp_php:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

}

5、创建Nginx容器 ,容器加入lnmp网络,宿主机端口88转发容器80端口,数据挂载方式bind,将nginx.conf文件挂载到容器中
#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
6、以wordpress博客为例
https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz
将wordpress解压到/var/lib/docker/volumes/wwwroot/_data下

8.Docker 图形化管理
Portainer是一款开源的Dockert图像管理系统
官网:https://www.portainer.io
https://www.portainer.io/installation/按照官方文档操作即可
Portainer安装
[root@osce ~]# docker volume create portainer_data
[root@osce ~]#docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
[root@osce ~]# docker ps
待容器启动后通过IP+9000端口访问
第一次访问会提示修改密码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值