Docker入门与进阶(上)

作者

刘畅

时间

2020-10-17

目录

1 Docker核心概述与安装 1

1.1
为什么要用容器 1

1.2
docker是什么 1

1.3
docker设计目标 1

1.4
docker基本组成 1

1.5
容器vs虚拟机 2

1.6
docker应用场景 2

1.7
安装docker 2

2 Docker镜像管理 3

2.1
什么是镜像 3

2.2
镜像从哪里来 4

2.3
镜像与容器联系 4

2.4
镜像常用管理命令 4

2.5
镜像存储核心技术(联合文件系统UnionFS) 5

2.6
镜像存储核心技术(写时复制Cow) 6

3 Docker容器管理 6

3.1
创建容器常用选项 6

3.2
容器资源限制 7

3.3
容器资源配额扩容 7

3.4
管理容器常用命令 7

3.5
容器实现核心技术(Namespace) 8

3.6
容器实现核心技术(CGroups) 9

3.7
docker核心组件之间关系 10

3.8
小结 10

4 Docker容器数据持久化 11

4.1
将数据从宿主机挂载到容器中的三种方式 11

4.2
Volume 11

4.3
Bind Mounts 12

4.4
小结 12

5 Docker容器网络 13

5.1
四种网络模式 13

5.2
Docker网络模型 15

5.3
容器网络访问原理 15

5.4
容器网络实现核心技术(Iptables) 16

5.5
跨主机网络(实现Docker主机容器通信) 17

6 Dockerfile定制容器镜像 22

6.1
Dockerfile介绍 22

6.2
Dockerfile常用指令 22

6.3
docker
build构建镜像 22

6.4
CMD与ENTRYPOINT区别 23

6.5
前端项目镜像构建与部署(Nginx) 24

6.6
PHP项目镜像构建(PHP) 25

6.7
案例(容器化搭建个人博客系统) 26

6.8
JAVA项目镜像构建(Tomcat) 27

6.9
JAVA微服务镜像构建(Jar) 29

6.10
编写Dockerfile最佳实践 30

7 补充 30

1 子网 30

1 Docker核心概述与安装

1.1
为什么要用容器

(1) 上线流程繁琐

开发->测试->申请资源->审批->部署->测试等环节

(2) 资源利用率低

普遍服务器利用率低,造成过多浪费

(3) 扩容/缩容不及时

业务高峰期扩容流程繁琐,上线不及时

(4) 服务器环境臃肿

服务器越来越臃肿,对维护、迁移带来困难

(5) 环境不一致性

1.2
docker是什么

(1)
使用最广泛的开源容器引擎

(2)
一种操作系统级的虚拟化技术

(3)
依赖于Linux内核特性:Namespace(资源隔离)和Cgroups(资源限制)

(4)
一个简单的应用程序打包工具

1.3
docker设计目标

(1)
提供简单的应用程序打包工具

(2) 开发人员和运维人员职责逻辑分离

(3) 多环境保持一致性

1.4
docker基本组成

1.5
容器vs虚拟机

1.6
docker应用场景

(1)
应用程序打包和发布

(2) 应用程序隔离

(3) 持续集成

(4) 部署微服务

(5) 快速搭建测试环境

(6) 提供PaaS产品(平台即服务)

1.7
安装docker

Docker版本:

社区版(Community
Edition,CE)

企业版(Enterprise
Edition,EE)

支持平台:

Linux(CentOS,Debian,Fedora,Oracle
Linux,RHEL,SUSE和Ubuntu)

Mac

Windows

# 安装依赖包

[root@slavenode1 ~]# yum install -y yum-utils
device-mapper-persistent-data lvm2

# 添加Docker软件包源

[root@slavenode1 ~]# yum-config-manager
\

--add-repo \

https://download.docker.com/linux/centos/docker-ce.repo

# 更新为阿里云的源

[root@slavenode1 ~]# wget -O
/etc/yum.repos.d/docker-ce.repo
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 清理源缓存

[root@slavenode1 ~]# yum clean all

# 安装Docker
CE

[root@slavenode1 ~]# yum install -y
docker-ce

# 启动Docker服务并设置开机启动

[root@slavenode1 ~]# systemctl start
docker

[root@slavenode1 ~]# systemctl enable
docker

# 查看docker版本

[root@slavenode1 ~]# docker -v

Docker version 19.03.12, build
48a66213fe

# 添加阿里云的镜像仓库

[root@slavenode1 ~]# mkdir -p
/etc/docker

[root@slavenode1 ~]# tee /etc/docker/daemon.json
<<-'EOF'

{

"registry-mirrors":
["https://b1cx9cn7.mirror.aliyuncs.com"]

}

EOF

# 重启docker

[root@slavenode1 ~]# systemctl
daemon-reload

[root@slavenode1 ~]# systemctl restart
docker

2 Docker镜像管理

2.1
什么是镜像

(1)
一个分层存储的文件,不是一个单一的文件

(2)
一个软件的环境

(3)
一个镜像可以创建N个容器

(4)
一种标准化的交付

(5)
一个不包含Linux内核而又精简的Linux操作系统

2.2
镜像从哪里来

Docker Hub是由Docker公司负责维护的公共镜像仓库,包含大量的容器镜像,Docker工具默认从这个公共镜像库下载镜像。

地址:https://hub.docker.com

2.3
镜像与容器联系

镜像:类似于虚拟机镜像,一个只读模板

容器:通过镜像创建的运行实例

2.4
镜像常用管理命令

指令

描述

ls

列出镜像

build

构建镜像来自Dockerfile

history

查看镜像历史

inspect

显示一个或多个镜像详细信息

pull

从镜像仓库拉取镜像, 分层下载,默认镜像版本latest

push

推送一个镜像到镜像仓库

rm

移除一个或多个镜像

prune

移除没有被标记或者没有被任何容器引用的镜像

tag

创建一个引用源镜像标记目标镜像

export

导出容器文件系统到tar归档文件

import

导入容器文件系统tar归档文件创建镜像

save

保存一个或多个镜像到一个tar归档文件

load

加载镜像来自tar归档或标准输入

(1)
清理镜像

docker image
prune -f  # 不提示确认(-f)清除没有tag的镜像

docker image prune -a -f  # 不提示确认(-f)清除没有被容器使用的镜像

(2)
export、import方式导入镜像

docker
export 容器名/容器ID
> 打包容器名.tar

docker import
打包容器名.tar
自定义镜像名:版本号

(3)
save、load方式导入镜像

docker save
-o 打包镜像名.tar 镜像名称:版本号

docker
load -i 打包镜像名.tar

(4)
docker export和docker save的区别

1) docker save保存的是镜像(image),docker export保存的是容器(container)。

2) docker load用来载入镜像包,docker
import用来载入容器包,但两者都会恢复为镜像。

3) docker load不能对载入的镜像重命名,而docker import可以为镜像指定新名称。

4) docker export导出的镜像文件大小小于save保存的镜像。

5) docker save 没有丢失镜像的历史,可以回滚到之前的层(layer)。(查看方式:docker images --tree)docker export 再导入时会丢失镜像所有的历史,所以无法进行回滚操作(docker tag
<LAYER ID> <IMAGE NAME>)。

(5)
其它命令

docker images #
列出所有镜像

docker image
rm -f 镜像名或ID # 强制(-f)删除镜像,如果镜像正在被运行的容器使用不会被删除。

docker image rm -f $(docker images
-q) # 强制(-f)删除所有的镜像,如果镜像正在被运行的容器使用不会被删除。

2.5
镜像存储核心技术(联合文件系统UnionFS)

镜像怎么高效存储,难道像虚拟机那样一个容器对应一个独立的镜像文件,这样对于密集型容器,磁盘占用率太大,引入联合文件系统,将镜像多层文件联合挂载到容器文件系统。

镜像存储目录: /var/lib/docker/overlay2/

容器目录: /var/lib/docker/containers/

读文件: 容器层->镜像层

修改文件: 容器层->镜像层

MergedDir(视图层)

UpperDir(容器层)

LowerDir(镜像层)

Storage Driver: overlay2(aufs、overlay、devicemapper)

2.6
镜像存储核心技术(写时复制Cow)

了解联合文件系统后,我们知道,镜像是只读的,类似共享形式让多个容器使用,如果要在容器里修改文件,即镜像里的文件,那该怎么办呢,这时就需要引入写时复制(copy-on-write),需要修改文件操作时,会先从镜像里把要写的文件复制到自己的文件系统中进行修改。

docker存储优化建议:

使用SSD固态硬盘

使用卷作为频繁读写文件的工作目录,绕过存储驱动,减少抽象的开销

3 Docker容器管理

3.1
创建容器常用选项

-i, --interactive

交互式

-t, --tty

分配一个伪终端

-d, --detach

运行容器到后台

-e, --env

设置环境变量

-p, --publish list

发布容器端口到主机

-P, --publish-all

发布容器所有EXPOSE的端口到宿主机随机端口

--name string

指定容器名称

-h, --hostname

设置容器主机名(同时也加入到/etc/hosts文件解析)

--add-host host:ip

设置容器hosts

--dns

设置容器resolv.conf

--ip string

指定容器IP,只能用于自定义网络

--network

连接容器到一个网络(bridge,host,none)

--mount mount

将文件系统附加到容器

-v, --volume list

绑定挂载一个卷

--restart string

容器退出时重启策略,默认no,可选值:[always|on-failure]

参数后面加的值可以用"="或空格隔离。

创建容器时,容器会挂载宿主机三个文件(宿主机修改,需要重启容器):

hostname         --hostname

hosts --add-host host:ip

resolv.conf       --dns

3.2
容器资源限制

选项

描述

-m,--memory

容器可以使用的最大内存量

--memory-swap

允许交换到磁盘的内存量,表示内存和 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.3
容器资源配额扩容

1 内存限额

允许容器最多使用500M内存和100M的Swap,并禁用OOM Killer:

docker run -d --name nginx03 --memory="500m"
--memory-swap="600m" --oom-kill-disable nginx

# --memory用于限制内存使用量,而--memory-swap则表示内存和Swap的总和。

# 如果只指定了--memory,则最终--memory-swap将会设置为--memory的两倍。

# 如果--memory-swap和--memory设置了相同值,则表示不使用Swap。

# 如果设置了--memory-swap参数,则必须设置--memory参数。

# --oom-kill-disable:触发oom异常不杀死容器(当内核检测到没有足够的内存来运行系统的

某些功能时,触发OOM异常,并且会使用OOM Killer来杀掉一些进程,腾出空间以保障

系统的正常运行。)

2 CPU限额

(1)
允许容器最多使用一个半的CPU

docker run -d --name nginx04 --cpus="1.5"
nginx

(2)
允许容器最多使用50%的CPU

docker run -d --name nginx05 --cpus=".5"
nginx

3.4
管理容器常用命令

选项

描述

ls

列出正在运行的容器

inspect

查看一个或多个容器详细信息

exec

在运行容器中执行命令

commit

创建一个新镜像来自一个容器

cp

拷贝文件/文件夹到一个容器

logs

获取一个容器日志

port

列出或指定容器端口映射

top

显示一个容器运行的进程

stats

显示容器资源使用统计

stop/start/restart

停止/启动/重启/一个或多个容器

rm

删除一个或多个容器

prune

移除已停止的容器

docker container
ps # 列出正在运行的容器

docker container
ps -l # 列出最近一次操作的容器

docker container
ps -a   # 列出所有容器,包括停止和运行的容器

docker container ps -aq  #
列出所有容器ID

docker container
prune -f # 不提示确认(-f)删除已停止的容器

docker container rm -f
容器名或id # 强制(-f)删除指定的容器

docker container exec -it 容器名或id  bash # 进入容器

docker container update lc12_nginx --memory 500m
--memory-swap="500m"

# 更新容器配置(默认创建的容器使用宿主机所有资源)

# 本质:echo "1000m" >
/sys/fs/cgroup/memory/docker/<容器id>/memory.memsw.limit_in_bytes

echo "500m" >
/sys/fs/cgroup/memory/docker/<容器id>/memory.limit_in_bytes

docker container
rm -f $(docker ps -qa) #
强制(-f)删除所有的容器(包括正在运行的容器)

3.5
容器实现核心技术(Namespace)

1 在容器化中,一台物理计算机可以运行多个不同操作系统,那就需要解决“隔离性”,彼此感知不到对方存在,有问题互不影响。Linux内核从2.4.19版本开始引入了namespace概念,其目的是将特定的全局系统资源通过抽象方法使得namespace中的进程看起来拥有自己隔离的资源。Docker就是借助这个机制实现了容器资源隔离。

2 Linux的Namespace机制提供了6种不同命名空间

ll /proc/$$/ns #
查看进程的命名空间

(1)
IPC:隔离进程间通信

(2)
MOUNT:隔离文件系统挂载点

(3)
NET:隔离网络协议栈

(4) PID:隔离进程号,进程命名空间是一个父子结构,子空间对父空间可见

(5)
USER:隔离用户

(6)
UTS:隔离主机名和域名

3.6
容器实现核心技术(CGroups)

1 Docker利用namespace实现了容器之间资源隔离,但是namespace不能对容器资源限制,

比如CPU、内存。如果某一个容器属于CPU密集型任务,那么会影响其他容器使用CPU,

导致多个容器相互影响并且抢占资源。如何对多个容器的资源使用进行限制就成了容器化

的主要问题。

2 引入Control Groups(简称CGroups),限制容器资源CGroups,所有的任务就是运行在系统

中的一个进程,而CGroups以某种标准将一组进程为目标进行资源分配和控制。例如CPU、内

存、带宽等,并且可以动态配置。

3 CGroups主要功能

(1)
限制进程组使用的资源数量(Resource
limitation),可以为进程组设定资源使用上限,例如

内存

(2)
进程组优先级控制(Prioritization),可以为进程组分配特定CPU、磁盘IO吞吐量。

(3)
记录进程组使用的资源数量(Accounting),例如使用记录某个进程组使用的CPU时间。

(4)
进程组控制(Control),可以将进程组挂起和恢复。

4 查看cgroups可控制的资源

ls /sys/fs/cgroup/ -l

(1) blkio # 对快设备的IO进行限制。

(2) cpu # 限制CPU时间片的分配,与cpuacct挂载同一目录。

(3) cpuacct # 生成cgroup中的任务占用CPU资源的报告,与cpu挂载同一目录。

(4) cpuset # 给cgroup中的任务分配独立的CPU(多核处理器)和内存节点。

(5) devices # 允许或者拒绝 cgroup 中的任务访问设备。

(6) freezer # 暂停/恢复 cgroup
中的任务。

(7) hugetl # 限制使用的内存页数量。

(8) memory # 对cgroup
中任务的可用内存进行限制,并自动生成资源占用报告。

(9) net_cls # 使用等级识别符(classid)标记网络数据包,这让Linux流量控制

程序(tc)可以识别来自特定从cgroup 任务的数据包,并进行网络限制。

(10) net_prio # 允许基于cgroup设置网络流量的优先级。

(11) perf_event #允许使用perf工具来监控cgroup。

(12) pids # 限制任务的数量。

(13) /sys/fs/cgroup/<资源名>/docker/<容器ID> # 容器实际资源限制位置

3.7
docker
核心组件之间关系

(1)
Docker Daemon

Docker守护进程,负责与Docker
Clinet交互,并管理镜像、容器。

(2) Containerd

是一个简单的守护进程,向上给Docker Daemon提供接口,向下通过containerd-shim

结合runC管理容器。

(3) runC

一个命令行工具,它根据OCI标准来创建和运行容器

3.8
小结

1 Namespace

命名空间,Linux内核提供的一种对进程资源隔离的机制,例如进程、网络、挂载点等资源。

2 CGroups

控制组,Linux内核提供的一种对进程组限制资源的机制;例如CPU、内存等资源。

3 UnionFS

联合文件系统,支持将不同位置的目录挂载到同一虚拟文件系统,形成一种分层的模型。

4 Docker容器数据持久化

4.1
将数据从宿主机挂载到容器中的三种方式

数据卷目录名称,指定的源目录/指定的源文件 :指定容器内的目录/指定容器内的文件/(如果目标不存在会自动创建)

容器被删除后不会删除卷,卷是容器的一个独立的资源。

(1)
volumes

Docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)。

(2)
bind mounts

将宿主机上的任意位置的文件或者目录挂载到容器中。

(3)
tmpfs

挂载存储在主机系统的内存中,而不会写入主机的文件系统。如果不希望将数据持久

存储在任何位置,可以使用tmpfs,同时避免写入容器可写层提高性能。

4.2 Volume

1 管理卷

# docker volume create nginx-vol

# docker volume ls

# docker volume inspect nginx-vol

2 用卷创建一个容器

# docker run -d --name=nginx-test --mount
src=nginx-vol,dst=/usr/share/nginx/html nginx

# docker run -d --name=nginx-test -v
nginx-vol:/usr/share/nginx/html nginx

3 清理

# docker stop nginx-test

# docker rm nginx-test

# docker volume rm nginx-vol

4 注意点

volume 挂载注意点(目录对目录):

(1) 宿主机目录不存在也能挂载成功

(2) 如果宿主机目录为空,会继承容器目录中的全部内容

(3) 如果宿主机目录不为空,会覆盖容器目录中的全部内容

(4) 源数据卷由docker进行管理

4.3 Bind Mounts

1 用卷创建一个容器

# docker run -d --name=nginx-test --mount
type=bind,src=/app/wwwroot,dst=/usr/share/nginx/html nginx

# docker run -d --name=nginx-test -v /app/wwwroot:/usr/share/nginx/html
nginx

2 验证绑定

# docker inspect nginx-test

3 清理

# docker stop nginx-test

# docker rm nginx-test

4 注意点

bind mounts 注意点(目录对目录或文件对文件):

(1)
宿主机文件或者目录必须存在才能成功挂载

(2) 宿主机目录覆盖容器目录中的全部内容

(3) 宿主机文件覆盖容器中指定的文件

(4)
使用-v参数挂卷时,如果源目录不存在也会创建

4.4
小结

1 Volume特点

(1)
将容器的数据存储在远程主机或其他存储上(间接)。

(2)
多个运行容器之间共享数据,多个容器可以同时挂载相同的卷。

(3)
当容器停止或被移除时,该卷依然存在。

(4)
当明确删除卷时,卷才会被删除。

(5)
将数据从一台Docker主机迁移到另一台时,先停止容器,然后备份卷的目录(/var/lib/docker/volumes/)。

2 Bind Mounts特点

(1)
从主机共享配置文件到容器。

(2)
在Docker主机上的开发环境和容器之间共享源代码。例如,可以将Maven target

目录挂载到容器中,每次在Docker主机上构建Maven项目时,容器都可以访问构建

的项目包。

(3) 当Docker主机的文件或目录结构保证与容器所需的绑定挂载一致时。

5 Docker容器网络

5.1
四种网络模式

(1) bridge

--net=bridge

默认网络,Docker启动后创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。

也可以自定义网络,相比默认的具备内部DNS发现,可以通过容器名(--name)进行容器之

间网络通信,可以解决因重建容器导致容器ip发生改变,导致前端应用无法连接后端服务

的问题。

小结:

1) 不通容器之间,主机和容器之间是完全隔离的。

2) docker0桥类似于一个交换机,把这个桥下的所有容器都连接起来,起到一个二层数据转

发的功能。

3) veth设备解决容器和宿主机之间网络命名空间隔离的问题。

4) 宿主机能到达的外部网络,容器都能够到达。

5) 宿主机可以访问其下的所有宿主机。

6) 同一宿主机内不同桥接网卡下的容器不能通信。

(2) host

--net=host

容器不会获得一个独立的network
namespace,而是与宿主机共用一个。这就意味着容器不

会有自己的网卡信息,而是使用宿主机的,容器除了网络,其他都是隔离的。

示例:

# docker run -d -it --name nginx_v4 --net=host busybox
sh

# docker exec -it nginx_v4 sh

进入nginx_v4容器内查看的网卡信息和宿主机上的网卡相同。

(3) none

--net=none

获取独立的network
namespace,但不为容器进行任何网络配置,需要我们手动配置。

示例:

# docker run -d -it --name nginx_v3 --net none busybox
sh

# docker exec -it nginx_v3 sh

除了本地环回网卡(lo),没有其他的网卡信息。

(4) container

--net=container:Name/ID

与指定的容器使用同一个network
namespace,具有同样的网络配置信息,两个容器除了网络,

其他都还是隔离的。

示例:

nginx_v1使用的bridge网络,nginx_v2共享nginx_v1的网络

# docker run -d -it --name nginx_v1 busybox
sh

# docker run -d -it --name nginx_v2
--net=container:nginx_v1 busybox sh

# docker exec -it nginx_v1 sh

# docker exec -it nginx_v2 sh

(6)
查看网络docker网络信息

# docker network ls

5.2
Docker网络模型

(1) veth pair

成对出现的一种虚拟网络设备,数据从一端进,从另一端出。用于解决网络命名空间之间隔离。

(2)
docker0

网桥是一个二层网络设备,通过网桥可以将Linux支持的不同的端口连接起来,并实现类似交

换机那样的多对多的通信。

5.3
容器网络访问原理

1 外部访问容器

2 容器访问外部

3 小结

5.4
容器网络实现核心技术(Iptables)

1 iptables基础知识

(1)
四表五链

filter(过滤)

INPUT、OUTPUT、FORWARD

nat(地址转换)

PREROUTING、POSTROUTING、OUTPUT

mangle(拆包、修改、封装)

INPUT、OUTPUT、PREROUTING、POSTROUTING、OUTPUT

raw(数据包状态跟踪)

PREROUTING、OUTPUT

(2)
操作命令

2 容器网络实现核心技术

(1)
Iptables
工作流程

INPUT链 # 接收的数据包是本机(入站)时,应用此链中的规则。

OUTPUT链 # 本机向外发送数据包(出站)时,应用此链中的规则。

FORWARD链 # 需要通过防火墙中转发送给其他地址的数据包(转发)

# 时,应用测链中的规则。

PREROUTING链 # 在对数据包做路由选择之前,应用此链中的规则。DNAT

POSTROUTING链 # 在对数据包做路由选择之后,应用此链中的规则。SNAT

5.5
跨主机网络(实现Docker主机容器通信)

通过桥接的方式实现

1 实验环境

主机名

IP地址

安装软件

etcd

172.16.1.71

etcd

docker01

172.16.1.72

docker、flannel

docker02

172.16.1.73

docker、flannel

Flannel是CoreOS维护的一个网络组件,在每个主机上运行守护进程,负责维护本地路由转

发,Flannel使用ETCD来存储容器网络与主机之间的关系。其他主流容器跨主机网络方案有:Weave、Calico、OpenvSwitch

2 ectd安装配置

在172.16.1.71节点上操作

(1)
安装ectd

# yum install etcd -y

# egrep -v "^$|^#"
/etc/etcd/etcd.conf

ETCD_DATA_DIR="/var/lib/etcd/default.etcd"

ETCD_LISTEN_CLIENT_URLS="http://172.16.1.71:2379"

ETCD_NAME="default"

ETCD_ADVERTISE_CLIENT_URLS="http://172.16.1.71:2379"

# systemctl start etcd.service

# systemctl enable etcd.service

# netstat -tunlp | grep etcd

(2)
向etcd写入子网

# etcdctl --endpoints="http://172.16.1.71:2379" set
/atomic.io/network/config '{ "Network":"172.17.0.0/16", "Backend": {"Type":
"vxlan"} }'

# 注意:子网地址不要和宿主机上的网段冲突

3 flannel安装并配置

在172.16.1.72、73节点上操作

(1)
安装flannel

# yum install flannel -y

# egrep -v "^$|^#"
/etc/sysconfig/flanneld

FLANNEL_ETCD_ENDPOINTS="http://172.16.1.71:2379"

FLANNEL_ETCD_PREFIX="/atomic.io/network"

# systemctl start flanneld.service

# systemctl enable flanneld.service

(2)
查看flannel网络信息

1) 172.16.1.72节点

# cat /var/run/flannel/docker

DOCKER_OPT_BIP="--bip=172.17.72.1/24"

DOCKER_OPT_IPMASQ="--ip-masq=true"

DOCKER_OPT_MTU="--mtu=1450"

DOCKER_NETWORK_OPTIONS=" --bip=172.17.72.1/24
--ip-masq=true --mtu=1450"

2) 172.16.1.73节点

# cat /var/run/flannel/docker

DOCKER_OPT_BIP="--bip=172.17.66.1/24"

DOCKER_OPT_IPMASQ="--ip-masq=true"

DOCKER_OPT_MTU="--mtu=1450"

DOCKER_NETWORK_OPTIONS=" --bip=172.17.66.1/24 --ip-masq=true
--mtu=1450"

4 配置Docker使用flannel生成的网络信息

在172.16.1.72、73节点上操作

(1)
配置docker systemd引用flannel的分配的网络

# vim /usr/lib/systemd/system/docker.service

EnvironmentFile=/run/flannel/docker

ExecStart=/usr/bin/dockerd -H fd://
--containerd=/run/containerd/containerd.sock $DOCKER_NETWORK_OPTIONS

(2)
重启docker

# systemctl restart docker

5 查看172.16.1.72、73节点的网卡信息

(1)
172.16.1.72节点

(2)
172.16.1.73节点

6 设置iptables允许转发

在172.16.1.72、73节点上操作

# iptables -P FORWARD ACCEPT

7 测试

(1)
在172.16.1.72节点上创建名为nginx_v72的容器

# docker run -d -it --name nginx_v72 busybox sh

# docker exec -it nginx_v72 sh

(2)
在172.16.1.73节点上创建名为nginx_v73的容器

# docker run -d -it --name nginx_v73 busybox
sh

# docker exec -it nginx_v73 sh

(3)容器nginx_v72
ping 容器nginx_v73

(4)
容器nginx_v73 ping
容器nginx_v72

(5)
在宿主机下访问容器ip地址

1) 使用docker01主机ping nginx_v72、nginx_v73容器

2) 使用docker02主机ping nginx_v72、nginx_v73容器

8 查看宿主机路由

(1) 172.16.1.72节点

(2)
172.16.1.73节点

6 Dockerfile定制容器镜像

6.1
Dockerfile介绍

6.2
Dockerfile常用指令

指令

描述

FROM

构建新镜像是基于哪个镜像

LABEL

标签

RUN

构建镜像时运行的Shell命令

COPY

拷贝文件或目录到镜像中

ADD

解压压缩包并拷贝

ENV

设置环境变量

USER

USER为RUN、CMD和ENTRYPOINT执行命令指定运行用户

EXPOSE

声明容器运行的服务端口

WORKDIR

WORKDIR为RUN、CMD、ENTRYPOINT、COPY和ADD设置工作目录

CMD

CMD运行容器时默认执行,如果有多个CMD指令,最后一个生效

ENTRYPOINT

ENTRYPOINT如果与CMD一起用,CMD将作为ENTRYPOINT的默认参数,如果有多个

6.3
docker build构建镜像

Usage: docker build [OPTIONS] PATH | URL | -
[flags]

Options:

-t, --tag list # 镜像名称

-f, --file string #
指定Dockerfile文件位置,如果构建文件是Dockerfile,可以不指定。

PATH:

构建镜像时所需文件的存放目录,Dockerfile文件中从宿主机上读取文件的命令都是从这

个目录里读取的。

# docker build -t shykes/myapp .

# docker build -t shykes/myapp -f /path/Dockerfile
/path

# docker build -t shykes/myapp
http://www.example.com/Dockerfile

6.4
CMD与ENTRYPOINT区别

1 CMD用法

(1)
exec形式(首选)

CMD ["executable", "param1",
"param2"]

CMD ["/usr/bin/sh", "-c", "executable param1 $param2"]

# 传递Dockerfile中定义的变量

(2)
shell形式

CMD command param1 param2

2 ENTRYPOINT用法

(1)
exec形式(首选)

ENTRYPOINT ["executable", "param1",
"param2"]

ENTRYPOINT ["/usr/bin/sh", "-c", "executable param1
$param2"]

# 传递Dockerfile中定义的变量

(2)
shell形式

ENTRYPOINT command param1 param2

3 ENTRYPOINT和CMD结合使用

ENTRYPOINT [ "executable" ]

CMD [ "param1", "param2" ]

# CMD作为ENTRYPOINT的默认参数

4 小结

(1) CMD和ENTRYPOINT指令都可以用来定义运行容器时所使用的默认命令,

使用方法相同。

(2) Dockerfile至少指定一个CMD或ENTRYPOINT,如果Dockerfile中定义了

多个CMD或多个ENTRYPOINT,只有最后一个定义生效。

(3)
docker
run指定<command>时,将会覆盖CMD,ENTRYPOINT不会被覆盖。

(4)
如果是可执行文件,希望docker run时传参,应该使用ENTRYPOINT作执

行文件,CMD用作ENTRYPOINT的默认参数。好处是,用户不传参时使用默

认的CMD参数,用户自定义传参时覆盖默认参数,方便用户灵活传参。

6.5 前端项目镜像构建与部署(Nginx)

1 Dockerfile文件

# ls /tools/DockerFile/nginx/

Dockerfile  nginx-1.19.1.tar.gz  nginx.conf  php.conf

# cat
/tools/DockerFile/nginx/Dockerfile

FROM centos:7

LABEL maintainer liuchang

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 groupadd -g 1200 nginx &&
\

useradd -M -s /sbin/nologin -u
1200 -g nginx nginx

COPY nginx-1.19.1.tar.gz /

RUN tar -zxf nginx-1.19.1.tar.gz &&
\

cd nginx-1.19.1 &&
\

./configure
--prefix=/usr/local/nginx \

--with-http_ssl_module
\

--with-http_stub_status_module
\

--user=nginx
\

--group=nginx &&
\

make -j 4 && make
install && \

rm -rf /usr/local/nginx/html/*
&& \

cd / && rm -rf nginx*
&& \

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;"]

2 构建nginx镜像

# docker build -t nginx:v1 -f
/tools/DockerFile/nginx/Dockerfile /tools/DockerFile/nginx/

# docker images

REPOSITORY      TAG              IMAGE
ID          CREATED           SIZE

nginx            v1               24ed66fdbc2d      17 minutes ago      337MB

6.6
PHP项目镜像构建(PHP)

1 Dockerfile文件

# ls /tools/DockerFile/php/

Dockerfile  php-7.2.19.tar.gz  php-fpm.conf  php.ini  wordpress-5.4.2.tar.gz  www.conf

# cat
/tools/DockerFile/php/Dockerfile

FROM centos:7

LABEL maintainer liuchang

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 groupadd -g 1200 nginx &&
\

useradd -M -s /sbin/nologin -u
1200 -g nginx nginx

COPY php-7.2.19.tar.gz /

RUN tar -zxf php-7.2.19.tar.gz &&
\

cd php-7.2.19 &&
\

./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 \

--with-fpm-user=nginx
\

--with-fpm-group=nginx
&& \

make -j 4 && make
install && \

cp -a php.ini-production
/usr/local/php/etc/php.ini && \

cp -a
/usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf
&& \

cp -a
/usr/local/php/etc/php-fpm.d/www.conf.default
/usr/local/php/etc/php-fpm.d/www.conf && \

sed -i 's/\;daemonize =
yes/daemonize = no/' /usr/local/php/etc/php-fpm.conf &&
\

sed -i
's/127.0.0.1:9000/0.0.0.0:9000/' /usr/local/php/etc/php-fpm.d/www.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/

COPY www.conf
/usr/local/php/etc/php-fpm.d/

WORKDIR /usr/local/php

EXPOSE 9000

CMD ["php-fpm"]

2 构建php镜像

# docker build -t php:v1 -f
/tools/DockerFile/php/Dockerfile /tools/DockerFile/php

# docker images

REPOSITORY          TAG                 IMAGE
ID            CREATED             SIZE

php                 v1                  eb8fc1539da5        11 minutes ago      574MB

6.7
案例(容器化搭建个人博客系统)

0 环境准备

# mkdir -p
/opt/php_wordpress/{mysql_data,mysql_cnf,nginx_conf,wwwroot}

# cp -a /tools/DockerFile/nginx/php.conf
/opt/php_wordpress/nginx_conf/

# cp -a /tools/DockerFile/mysql/my.cnf
/opt/php_wordpress/mysql_cnf/

1 自定义网络

# docker network create lnmp

2 创建mysql数据库

# docker run -d \

-p 3306:3306 --name lnmp_mysql
\

--net lnmp --restart=always
\

-v
/opt/php_wordpress/mysql_data:/var/lib/mysql \

-v
/opt/php_wordpress/mysql_cnf:/etc/mysql \

-v
/etc/localtime:/etc/localtime \

-e MYSQL_ROOT_PASSWORD=123456
\

-e MYSQL_DATABASE=wordpress
\

mysql:5.7
--character-set-server=utf8

3 创建php容器

# docker run -d \

--name lnmp_php --net lnmp \

-v /opt/php_wordpress/wwwroot:/usr/local/nginx/html
\

--restart=always php:v1

4 创建nginx容器

# docker run -d \

--name lnmp_nginx --net lnmp \

-p 80:80 \

-v /opt/php_wordpress/wwwroot:/usr/local/nginx/html
\

-v
/opt/php_wordpress/nginx_conf/php.conf:/usr/local/nginx/conf/conf.d/php.conf
\

--restart=always nginx:v1

5 以wordpress博客为例

(1)
解压wordpress安装包

# cd /opt/php_wordpress/wwwroot/

# tar -xzf
/tools/DockerFile/php/wordpress-5.4.2.tar.gz

# chown -R 1200:1200 wordpress/

(2)
访问

http://172.16.1.71/wordpress/

6.8
JAVA项目镜像构建(Tomcat)

1 Dockerfile文件

# ls /tools/DockerFile/tomcat/

apache-tomcat-8.5.43.tar.gz  catalina.sh  Dockerfile  jdk-8u45-linux-x64.tar.gz  jpress-v3.2.5.war  server.xml

# cat
/tools/DockerFile/tomcat/Dockerfile

FROM centos:7

LABEL maintainer liuchang

RUN yum install wget curl unzip iproute net-tools -y
&& \

yum clean all &&
\

rm -rf /var/cache/yum/*
&& \

ln -sf
/usr/share/zoneinfo/Asia/Shanghai /etc/localtime

COPY jdk-8u45-linux-x64.tar.gz /

RUN tar -xzf jdk-8u45-linux-x64.tar.gz &&
\

mv jdk1.8.0_45 /usr/local/jdk
&& \

rm -rf
jdk-8u45-linux-x64.tar.gz

COPY apache-tomcat-8.5.43.tar.gz /

RUN tar -zxf apache-tomcat-8.5.43.tar.gz &&
\

mv apache-tomcat-8.5.43
/usr/local/tomcat && \

rm -rf
apache-tomcat-8.5.43.tar.gz && \

rm -rf
/usr/local/tomcat/webapps/*

ENV JAVA_HOME /usr/local/jdk

ENV CLASSPATH
$JAVA_HOME/lib/tools.jar:$JAVA_HOME/jre/lib/rt.jar

ENV PATH
$JAVA_HOME/bin:/usr/local/tomcat/bin:$PATH

COPY catalina.sh
/usr/local/tomcat/bin

COPY server.xml
/usr/local/tomcat/conf

RUN chmod +x
/usr/local/tomcat/bin/catalina.sh

WORKDIR /usr/local/tomcat

EXPOSE 8080

CMD ["catalina.sh", "run"]

2 构建镜像

# docker build -t tomcat:v1 -f
/tools/DockerFile/tomcat/Dockerfile /tools/DockerFile/tomcat/

# docker images

REPOSITORY TAG     IMAGE ID            CREATED              SIZE

tomcat v1      4ea00c9980f3        About a minute ago     766MB

3 启动jpress网站测试

(1)
创建容器

# mkdir -p /opt/tomcat/webapp/

# cp /tools/DockerFile/tomcat/jpress-v3.2.5.war
/opt/tomcat/webapp/ROOT.war

# docker run -d \

--name tomcat_jp -p 8080:8080 \

-v /opt/tomcat/webapp:/usr/local/tomcat/webapps
\

--restart=always tomcat:v1

(2)
访问

http://172.16.1.71:8080/

6.9
JAVA微服务镜像构建(Jar)

1 构建镜像

# ls /tools/DockerFile/jdk/

Dockerfile  hello.jar  jdk-8u45-linux-x64.tar.gz

# cat
/tools/DockerFile/jdk/Dockerfile

FROM centos:7

LABEL maintainer liuchang

RUN yum install wget curl unzip iproute net-tools -y
&& \

yum clean all &&
\

rm -rf /var/cache/yum/*
&& \

ln -sf
/usr/share/zoneinfo/Asia/Shanghai /etc/localtime

COPY jdk-8u45-linux-x64.tar.gz /

RUN tar -xzf jdk-8u45-linux-x64.tar.gz &&
\

mv jdk1.8.0_45 /usr/local/jdk
&& \

rm -rf
jdk-8u45-linux-x64.tar.gz

ENV JAVA_HOME /usr/local/jdk

ENV CLASSPATH
$JAVA_HOME/lib/tools.jar:$JAVA_HOME/jre/lib/rt.jar

ENV PATH $JAVA_HOME/bin:$PATH

ENV JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF8
-Duser.timezone=GMT+08"

COPY hello.jar /

EXPOSE 8888

CMD ["/bin/sh", "-c", "java -jar $JAVA_OPTS
/hello.jar"]

2 启动镜像

# cd /tools/DockerFile/jdk/

# docker build -t jdk_ms:v1 .

# docker images

REPOSITORY TAG                 IMAGE
ID           CREATED        SIZE

jdk_ms v1                  3c3a5efb74fd        59
seconds ago     747MB

3 测试

# docker run -d --name micro_server
jdk_ms:v1

# docker logs micro_server

Hello world!

sleep 1 day...

6.10
编写Dockerfile最佳实践

(1) 减少镜像层

一次RUN、COPY、ADD指令会形成新的一层,尽量Shell命令都写在一行,减少镜像层。

(2) 优化镜像大小

一次RUN、COPY、ADD形成新的一层,如果没有在同一层删除,无论文件是否最后删除,

都会带到下一层,所以要在每一层清理对应的残留数据,减小镜像大小。

(3) 减少网络传输时间

例如软件包、mvn仓库等

(4) 多阶段构建

代码编译、部署在一个Dockerfile完成,只会保留部署阶段产生数据。

(5) 选择最小的基础镜像

例如alpine

7 补充

1 子网

能不能通信是建立在同一网段(网络号一致)的基础上的,并不是说子网掩码一致或不一致

就可以通信或不能通信。

举个例子:

192.168.0.1/24与192.168.0.2/25子网掩码分别是255.255.255.0与255.255.255.128,通过

ip地址与子网掩码与运算得出网络号均为192.168.0.0,即这两个 IP是属于同一网段,可

以通信。而192.168.0.1/25与192.168.0.65/25,虽然子网掩码一致,但不属于同一网段,

前者是192.168.0.0
后者是192.168.0.64,不能进行通信。

Docker入门与进阶(上)的更多相关文章

  1. Docker入门与进阶(下)

    Docker入门与进阶(下) 作者 刘畅 时间 2020-11-12 实验主机配置 系统centos7.5 主机名 ip 配置 应用 harbor-master 172.16.1.71 2核4G/60 ...

  2. 这可能是最为详细的Docker入门总结

    写在前面 毕设是关于区块链的,自然就用到了docker,感觉到了docker的强大.学习源于总结,所以找了一些资料,这篇文章原作写的不错,看了好多遍哈哈. 这可能是最为详细的Docker入门总结 市面 ...

  3. Docker入门系列之三:如何将dockerfile制作好的镜像发布到Docker hub上

    这个系列的前两篇文章,我们已经把我们的应用成功地在Docker里通过nginx运行了起来,并且用dockerfile里制作好了一个镜像. Docker入门系列之一:在一个Docker容器里运行指定的w ...

  4. Docker入门教程(五)Docker安全

    Docker入门教程(五)Docker安全 [编者的话]DockOne组织翻译了Flux7的Docker入门教程,本文是系列入门教程的第五篇,介绍了Docker的安全问题,依然是老话重谈,入门者可以通 ...

  5. Docker入门之七Dockerfile

    Dockerfile是一个文本格式的配置文本,可以使用它来创建自定义的镜像.首先我们可以先看一个dockerfile是什么样子.这里可以有一个网站不错:http://dockerfile.github ...

  6. 第三章 Docker 入门

    第三章 docker 入门 3.1 确保docker已经就绪 首先查看docker程序是否存在,功能是否正常 [#3#cloudsoar@cloudsoar-virtual-machine ~]$su ...

  7. 学习 Docker - 入门

    Docker简介 一种虚拟容器技术. 一种虚拟化分方案: 操作系统级别的虚拟化: 只能运行相同或相似内核的操作系统: 依赖与linux内核特性:Namespace和Cgroups(Control Gr ...

  8. Docker入门教程(九)10个镜像相关的API

    Docker入门教程(九)10个镜像相关的API [编者的话]DockerOne组织翻译了Flux7的Docker入门教程,本文是系列入门教程的第九篇,重点介绍了镜像相关的Docker Remote ...

  9. Docker入门教程(八)Docker Remote API

    Docker入门教程(八)Docker Remote API [编者的话]DockerOne组织翻译了Flux7的Docker入门教程,本文是系列入门教程的第八篇,重点介绍了Docker Remote ...

随机推荐

  1. Build 2021 :正式发布.NET 6 Preview4

    微软在不断推进.NET 6的可用性,昨晚的Build 2021大会上发布了Preview4, 这是一个很大的版本更新,带来大量的功能,以及接近最终的产品交付质量,不过,这并不意味着可以在生产环境使用了 ...

  2. [bug] jupyter notebook:服务在阿里云上启动,本地浏览器无法访问

    问题 在阿里云上装了个jupyter,服务正常启动了,但网页上无法访问 排查 安全组已经设置过了,7777端口 在宝塔面板查看,发现7777端口并没有开,打开就可以访问了 原来阿里云的安全组和防火墙是 ...

  3. [Java] 类库例题

    例1 字符串操作 定义一个StringBuffer类对象,然后通过append()方法向对象中添加26个小写字母,每次只添加一次,共添加26次,然后按逆序方式输出,并且可以删除前5个字符 面向过程实现 ...

  4. ubuntu查看已安装软件包信息的方法

    ubuntu查看已安装软件包信息的方法原创fang141x 最后发布于2019-04-15 10:41:34 阅读数 2802 收藏展开简介ubuntu下面是使用dpkg来管理和安装软件包的,对应ce ...

  5. nginx版本无缝升级与回滚

    chookie和session 你们公司的会话保持怎么做的? 1.开发做的:记录用户登陆的状态,将用户登陆状态保存到,redis服务器中,nfs,mysql. ​ 记录用户的登陆状态. ​ 通过登陆用 ...

  6. stm32.cube(一)——系统架构及目录结构

    一.前言 Arm的应用场景往往比51单片机复杂得多,如果一个高级应用的开发需要连底层的结构性代码都要重构,那么在成本和研发周期上就会面临巨大的风险.为了简化编码过程,芯片厂商经常会提供一些板卡级支持的 ...

  7. linux python3安装whl包时报错解决:is not a supported wheel on this platform

    原因1 你下载安装的包不是当前平台所支持的 原因2 你下载的包,不符合你所在的平台的安装whl的名称规范,所以出错.比如当前我要安装的包是:pymssql-2.1.5-cp36-cp36m-manyl ...

  8. linux中级之防火墙的数据传输过程

    网络数据传输过程 netfilter在数据包必须经过且可以读取规则的位置,共设有5个控制关卡.这5个关卡处的检查规则分别放在5个规则链中(有的叫钩子函数(hook functions).也就是说5条链 ...

  9. 在gin框架中使用JWT

    在gin框架中使用JWT JWT全称JSON Web Token是一种跨域认证解决方案,属于一个开放的标准,它规定了一种Token实现方式,目前多用于前后端分离项目和OAuth2.0业务场景下. 什么 ...

  10. Python+Selenium学习笔记12 - 窗口大小和滚动条

    涉及到的三个方法 set_window_size()  用于设置浏览器窗口的大小 e.gset_window_size(600,600) window.scrollTo() 用于设置浏览器窗口滚动条的 ...