docker实验计划

容器简介

为什么需要容器

容器解决了开发最麻烦的事情: 环境配置

用户必须保证两件事:操作系统的设置,各种库和组件的安装。只有它们都正确,软件才能运行。举例来说,安装一个 Python 应用,计算机必须有 Python 引擎,还必须有各种依赖,可能还要配置环境变量。

如果某些老旧的模块与当前环境不兼容,那就麻烦了。开发者常常会说:“它在我的机器可以跑了”,言下之意就是,其他机器很可能跑不了。

环境配置如此麻烦,换一台机器,就要重来一次,旷日费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装?也就是说,安装的时候,把原始环境一模一样地复制过来。

虚拟机–带环境安装的一种解决方案

它可以在一种操作系统里面运行另一种操作系统,比如在 Windows 系统里面运行 Linux 系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。

虽然用户可以通过虚拟机还原软件的原始环境。但是,这个方案有几个缺点。

  1. 资源占用大
    虚拟机需要独占一部分内存和硬盘空间, 即使里面的软件没有使用到,虚拟机依然要几百MB的内存
  2. 冗余步骤多(运行效率低下)
    虚拟机内部是完整的系统, 一些系统级的操作无法跳过,
  3. 启动慢
    虚拟机启动过程和真实的电脑完全一样

为了解决这些问题, 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

  1. 使用阿里云镜像下载
curl -sSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | sh -
  1. 安装需要的包
sudo apt-get install linux-image-extra-$(uname -r) linux-image-extra-virtual
  1. 添加使用 HTTPS 传输的软件包以及 CA 证书
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates
  1. 添加GPG密钥
sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
  1. 添加软件源
echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" | sudo tee /etc/apt/sources.list.d/docker.list
  1. 添加成功后更新软件包缓存
sudo apt-get update
  1. 安装docker
sudo apt-get install docker-engine
  1. 启动 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

  1. 打开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
  2. 按照提示安装docker
    可能因为系统缺乏wsl2导致失败,可以参照微软的文档解决: 安装 WSL https://docs.microsoft.com/zh-cn/windows/wsl/install
  3. 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的容器应用设计与部署实验总结_docker

在Docker Engine设置信息中加入镜像源地址

基于Docker的容器应用设计与部署实验总结_docker_02

加入

"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 命令查看运行者的容器

基于Docker的容器应用设计与部署实验总结_Docker_03

用mysql-cli连接localhost:3307测试数据库能不能连接上

在Docker Desktop图形界面可以看到所有容器与镜像, 为了兼顾Linux环境的同学, 这里全部是用命令写的.

实验2镜像: 构建镜像并且上传镜像到dockerHub(难度: 高)

实验需求:

  1. 已安装Docker
  2. 可以访问DockerHub与Gitee的网络

1. 构建镜像

  1. 使用git clone源代码或者在gitee下载下面项目的压缩包
    https://gitee.com/daniel8642/constellation-backend并且解压, 保证文件夹下有Dockerfile文件
  2. cd到项目文件夹内,使用ls可以看到Dockerfile
  3. 使用Dockerfile构建镜像
docker build -t <你的DockerHub用户名>/star-test:v0.1 .

star-test : 构建的镜像名

v0.1: 版本

. 使用本目录下的文件构建

基于Docker的容器应用设计与部署实验总结_mysql_04

看见 Successfully tagged <你的DockerHub用户名>/star-test:v0.1 构建就完成了

2. 检查镜像并运行测试镜像

  1. 使用docker images 打印镜像信息
    这里红色线上是我们要用的镜像
    蓝色是构建的中间镜像,可以删除
  2. 使用docker image rm 删除无用镜像
  3. 运行自己构建的镜像
  1. 运行数据库
docker run -itd --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=daniel8642 mysql
  1. 初始化数据库
    用MySQL-cli连接到机器3306端口
    创建数据库starWeb(与项目config.yaml中Mysql.database条目相同)
create database starWeb;

运行项目中initTable.sql中的数据表定义命令

  1. 运行镜像
    docker run -itd --name star-test -p 80:80 <自己构建的镜像ID>

    访问 <机器ip>/backend 可以显示网页即运行成功

3. 上传自定义镜像到DockerHub

要上传的镜像名称必须规范, 否则无法上传成功

镜像的完整名称是: 用户名称/仓库名称:TAG

如果名称不正确 可以使用docker tag 对镜像进行重命名

  1. 使用docker login进行登录
docker login

输入后按照提示输入DockerHub的用户名和密码

  1. docker push 用户名称/仓库名称:TAG 上传镜像
  2. 在dockerHub就可以查看到上传上去的镜像

实验3存储: 打通容器的文件系统(难度: 低)

Volume的生命周期长于容器. 容器被删除不会影响到Volumes

mysql镜像,与redis镜像都在makefile中设置了Volumes文件夹保存数据

实验使用centos手动用vi修改源文件模拟开发环境网页源文件的改动

  1. 初始化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端口检查容器运行结果

基于Docker的容器应用设计与部署实验总结_golang_05

  1. 初始化centos开发环境
    运行centos镜像,并且链接Volumes
docker run -itd -v nginx-vol:/web:rw --name centos-test centos:centos7
  1. 在宿主机检查实验结果
    进入容器命令行, 修改网页html文件
docker exec -it <容器ID> bash
cd web/
vi index.html

vi按i进入编辑模式

按esc退出编辑模式

输入 :wq 写入文件并退出

在文件修改完成后

刷新

http://localhost/

网页,可以看到网站已经改变

基于Docker的容器应用设计与部署实验总结_golang_06

实验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的容器一样
  • 模式比较特殊, 没有在下面图片中展示出来

用户还可以自己配置网络, 实现业务需求

基于Docker的容器应用设计与部署实验总结_mysql_07

实现容器之间相互访问有很多种方法

在实验一中, star项目中配置文件访问是数据库地址是172.17.0.1 .

这是docker中默认网桥docker0中宿主机的ip, 同时配置mysql容器映射到了宿主机3306端口

这一项实验我们将连接方式改为通过自定义网桥连接

  1. 新建网络
    先创建一个新的Docker网络
docker network create -d bridge my-net

基于Docker的容器应用设计与部署实验总结_golang_08

  1. 建立容器
    运行一个容器, 并且连接到新建的网络
    输入后终端会连接到容器内部, 保持这个终端不要关闭
docker run -it --rm --name busybox1 --network my-net busybox sh

基于Docker的容器应用设计与部署实验总结_docker_09

打开一个新的终端,输入命令新建另外一个容器, 保持终端不关闭

docker run -it --rm --name busybox2 --network my-net busybox sh

此时容器信息

基于Docker的容器应用设计与部署实验总结_golang_10

  1. 连通性测试
    在容器终端中相互ping
ping busybox1
ping busybox2

基于Docker的容器应用设计与部署实验总结_docker_11

基于Docker的容器应用设计与部署实验总结_docker_12

这里可以直接ping容器名, 因为docker在bridge型网络中默认开启dns解析. 可以把容器名解析成对应容器的ip