docker实验计划
容器简介
为什么需要容器
容器解决了开发最麻烦的事情: 环境配置
用户必须保证两件事:操作系统的设置,各种库和组件的安装。只有它们都正确,软件才能运行。举例来说,安装一个 Python 应用,计算机必须有 Python 引擎,还必须有各种依赖,可能还要配置环境变量。
如果某些老旧的模块与当前环境不兼容,那就麻烦了。开发者常常会说:“它在我的机器可以跑了”,言下之意就是,其他机器很可能跑不了。
环境配置如此麻烦,换一台机器,就要重来一次,旷日费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装?也就是说,安装的时候,把原始环境一模一样地复制过来。
虚拟机–带环境安装的一种解决方案
它可以在一种操作系统里面运行另一种操作系统,比如在 Windows 系统里面运行 Linux 系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。
虽然用户可以通过虚拟机还原软件的原始环境。但是,这个方案有几个缺点。
- 资源占用大
虚拟机需要独占一部分内存和硬盘空间, 即使里面的软件没有使用到,虚拟机依然要几百MB的内存 - 冗余步骤多(运行效率低下)
虚拟机内部是完整的系统, 一些系统级的操作无法跳过, - 启动慢
虚拟机启动过程和真实的电脑完全一样
为了解决这些问题, Linux 发展出了另一种虚拟化技术:Linux 容器
容器是什么
Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。
它是目前最流行的 Linux 容器解决方案。
Docker 将应用程序与该程序的依赖,打包在一个镜像文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。
总体来说,Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、就像管理普通的代码一样。
容器如何工作
Docker 基于Linux cgroups和Linux namespace技术实现. 可以理解成Docker是一种轻量化的虚拟机, 它打包了应用程序和所需的环境, 去除了内部客户操作系统
Dockerfile是什么
Dockerfile 类似于C与C++中的makefile ,内容是一条条构建镜像的指令. 这样在拥有项目源代码时可以方便的通过简单的一条指令构建镜像
新版本的Docker支持多阶段构建, 构建时合适的编译时基础镜像, 构建完成再将文件复制到合适的运行时基础镜像的容器中. 这样构建的镜像文件较小, 而且镜像中不带有源代码. 不存在源码泄露风险
多阶段构建的Dockerfile样例
# 第一阶段 :选择Maven基础镜像(Gradle类型也可以选择相应Gradle基础镜像)完成项目编译,拷贝源代码到基础镜像并运行RUN命令,从而构建Jar包。
FROM maven:3.5.0-jdk-8-alpine AS builder
# 从源代码中复制pom.xml与源代码
ADD ./pom.xml pom.xml
ADD ./src src/
# 将项目打包成jar文件
RUN mvn clean package
# 第二阶段:拷贝第一阶段生成的Jar包到OpenJDK镜像中,设置CMD运行命令。
From openjdk:8-jre-alpine
# 从第一阶段复制jar文件
COPY --from=builder target/my-app-1.0-SNAPSHOT.jar my-app-1.0-SNAPSHOT.jar
# 声明容器8080端口对外服务 在启动镜像时使用 -p <主机端口>:8080 连接端口 未指定会随机绑定一个空端口
EXPOSE 8080
#用 java -jar 运行my-app-1.0-SNAPSHOT.jar
CMD ["java", "-jar", "my-app-1.0-SNAPSHOT.jar"]
DockerHub是什么
DockerHub类似与GitHub, Gitee 是Docker官方的镜像托管平台. 封装好的镜像可以push到网站上, 然后在服务器上pull下载.同时提供了很多官方的公开镜像提供下载,常见的有Ubuntu, Nginx, Node.js, MySQL, Tomcat, Python, Redis
Volumes是什么?
为了能够保存(持久化)数据以及共享容器间的数据, 它的生命周期长于容器,可以被多个容器同时挂载
实验1容器: 实验环境准备(难度: 中)
1. 安装Docker
Docker 并非是一个通用的容器工具,它依赖于已存在并运行的 Linux 内核环境。
最新win版本是基于系统Linux子系统(WSL2)下的.
由于Docker Desktop for Windows 安装需要更改系统网卡设置, 常常和已安装好的虚拟机冲突. 如果系统原先有虚拟机(VMware, VirtualBox),建议在虚拟机上安装Ubuntu ,在Ubuntu 环境中安装
Ubuntu 环境
验证环境版本:
系统版本 | CentOS 7.6 64bit |
docker软件版本 | Docker-ce 19.03.9 |
机器配置 | 腾讯云CPU: 1核 内存: 2GB |
- 使用阿里云镜像下载
curl -sSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | sh -
- 安装需要的包
sudo apt-get install linux-image-extra-$(uname -r) linux-image-extra-virtual
- 添加使用 HTTPS 传输的软件包以及 CA 证书
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates
- 添加GPG密钥
sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
- 添加软件源
echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" | sudo tee /etc/apt/sources.list.d/docker.list
- 添加成功后更新软件包缓存
sudo apt-get update
- 安装docker
sudo apt-get install docker-engine
- 启动 docker服务并设置开机启动
sudo systemctl enable docker
sudo systemctl start docker
windows环境安装
验证环境版本:
系统版本 | Windows 11 专业版 21H2 |
docker软件版本 | Docker Desktop 4.5.1 (74721) |
机器配置 | 联想Y7000 i5-9300H 16.0 GB |
- 打开docker hub 下载Docker Desktop for Windows
网址: https://hub.docker.com/editions/community/docker-ce-desktop-windows
下载链接: https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe - 按照提示安装docker
可能因为系统缺乏wsl2导致失败,可以参照微软的文档解决: 安装 WSL https://docs.microsoft.com/zh-cn/windows/wsl/install - docker默认会从国外下载镜像,更换镜像源可以加速镜像下载
镜像地址:
- 科大镜像:https://docker.mirrors.ustc.edu.cn/
- 网易:https://hub-mirror.c.163.com/
- 阿里云:https://<你的TOKEN>.mirror.aliyuncs.com
- 七牛云加速器:https://reg-mirror.qiniu.com
阿里云地址需要在网站登录阿里云获取
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
打开设置
在Docker Engine设置信息中加入镜像源地址
加入
"registry-mirrors": [
"https://a1b2c3.mirror.aliyuncs.com"
]
注意要保证json格式正确
2. 克隆镜像
拉取mysql镜像
docker pull mysql:latest
3. 运行容器
docker run -itd --name mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
-d 让容器生成后在后台运行
-it 链接一个命令行
–name 给容器命名mysql
-p 将主机的3307端口映射到容器3306端口(3306端口是mysql默认端口)
-e 设定初始化参数MYSQL_ROOT_PASSWORD为123456, 这里是设置了root的密码
最末尾mysql 指定打开的镜像
4. 测试
可以使用 docker ps 命令查看运行者的容器
用mysql-cli连接localhost:3307测试数据库能不能连接上
在Docker Desktop图形界面可以看到所有容器与镜像, 为了兼顾Linux环境的同学, 这里全部是用命令写的.
实验2镜像: 构建镜像并且上传镜像到dockerHub(难度: 高)
实验需求:
- 已安装Docker
- 可以访问DockerHub与Gitee的网络
1. 构建镜像
- 使用git clone源代码或者在gitee下载下面项目的压缩包
https://gitee.com/daniel8642/constellation-backend并且解压, 保证文件夹下有Dockerfile文件 - cd到项目文件夹内,使用ls可以看到Dockerfile
- 使用Dockerfile构建镜像
docker build -t <你的DockerHub用户名>/star-test:v0.1 .
star-test : 构建的镜像名
v0.1: 版本
. 使用本目录下的文件构建
看见 Successfully tagged <你的DockerHub用户名>/star-test:v0.1 构建就完成了
2. 检查镜像并运行测试镜像
- 使用docker images 打印镜像信息
这里红色线上是我们要用的镜像
蓝色是构建的中间镜像,可以删除 - 使用docker image rm 删除无用镜像
- 运行自己构建的镜像
- 运行数据库
docker run -itd --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=daniel8642 mysql
- 初始化数据库
用MySQL-cli连接到机器3306端口
创建数据库starWeb(与项目config.yaml中Mysql.database条目相同)
create database starWeb;
运行项目中initTable.sql中的数据表定义命令
- 运行镜像
docker run -itd --name star-test -p 80:80 <自己构建的镜像ID>
访问 <机器ip>/backend 可以显示网页即运行成功
3. 上传自定义镜像到DockerHub
要上传的镜像名称必须规范, 否则无法上传成功
镜像的完整名称是: 用户名称/仓库名称:TAG
如果名称不正确 可以使用docker tag 对镜像进行重命名
- 使用docker login进行登录
docker login
输入后按照提示输入DockerHub的用户名和密码
- docker push 用户名称/仓库名称:TAG 上传镜像
- 在dockerHub就可以查看到上传上去的镜像
实验3存储: 打通容器的文件系统(难度: 低)
Volume的生命周期长于容器. 容器被删除不会影响到Volumes
mysql镜像,与redis镜像都在makefile中设置了Volumes文件夹保存数据
实验使用centos手动用vi修改源文件模拟开发环境网页源文件的改动
- 初始化Nginx容器
运行nginx容器,同时创建Volumes
docker run --name nginx-test -p 80:80 -v nginx-vol:/usr/share/nginx/html:rw -d nginx
-v volume名称:映射文件夹路径:rw或ro代表可读写与只读
在volume不存在时会创建新volume
访问宿主机80端口检查容器运行结果
- 初始化centos开发环境
运行centos镜像,并且链接Volumes
docker run -itd -v nginx-vol:/web:rw --name centos-test centos:centos7
- 在宿主机检查实验结果
进入容器命令行, 修改网页html文件
docker exec -it <容器ID> bash
cd web/
vi index.html
vi按i进入编辑模式
按esc退出编辑模式
输入 :wq 写入文件并退出
在文件修改完成后
刷新
网页,可以看到网站已经改变
实验4网络: 让容器轻松互联(难度: 低)
docker中的网络实际上都是网络虚拟化解决方案, 这里介绍docker自带的三种single-host网络
- none
- 相当于没有给容器连接网络, 适用与不需要网络连接的业务
- 容器内网卡只有本地环回地址127.0.0.1
- host
- 直接使用宿主机的网络, 容器系统申请到的端口对应宿主机的端口, 不需要定义开放的端口, 适合对传输效率有较高要求的容器,和一部分需要对网络进行配置的容器. 过度使用可能造成宿主机端口耗尽的问题
- 容器内网卡和宿主机完全一样
- bridge
- 默认的容器接入类型, 可以理解为容器被接入到虚拟的交换机. docker有一个默认的网桥docer0 网段是172.17.0.0/16 宿主机作为网关占用172.17.0.1
- 容器内网卡有本地环回, 和连接到网桥的网卡(可能有多个)
- joined container
- 类似host模式, 指定公用网络的容器
- 容器内网卡和被join的容器一样
- 模式比较特殊, 没有在下面图片中展示出来
用户还可以自己配置网络, 实现业务需求
实现容器之间相互访问有很多种方法
在实验一中, star项目中配置文件访问是数据库地址是172.17.0.1 .
这是docker中默认网桥docker0中宿主机的ip, 同时配置mysql容器映射到了宿主机3306端口
这一项实验我们将连接方式改为通过自定义网桥连接
- 新建网络
先创建一个新的Docker网络
docker network create -d bridge my-net
- 建立容器
运行一个容器, 并且连接到新建的网络
输入后终端会连接到容器内部, 保持这个终端不要关闭
docker run -it --rm --name busybox1 --network my-net busybox sh
打开一个新的终端,输入命令新建另外一个容器, 保持终端不关闭
docker run -it --rm --name busybox2 --network my-net busybox sh
此时容器信息
- 连通性测试
在容器终端中相互ping
ping busybox1
ping busybox2
这里可以直接ping容器名, 因为docker在bridge型网络中默认开启dns解析. 可以把容器名解析成对应容器的ip