Skip to content

项目实战

Docker容器化实战


学习该课程所得

  • 了解容器技术的概念,以及它如何改变应用程序开发和部署的方式。
  • 掌握容器的使用场景,理解容器与虚拟机之间的区别,以及它们各自的优势和限制。
  • 学会使用Docker进行基本操作,以及一些高级应用,如Docker Compose。
  • 掌握Docker的核心原理,包括镜像、容器、仓库等方面的知识。

容器技术介绍

容器技术是一种轻量级虚拟化技术,允许开发者将应用程序及其依赖项打包到一个独立的容器中。这些容器可以在不同的环境中运行,而不会受到环境差异的影响。容器技术具有以下优点:

  • 快速交付:容器可以快速创建、部署和启动,加速应用程序的交付过程。
  • 环境隔离:每个容器都是独立的,不会影响其他容器,确保应用程序的隔离性。
  • 轻量级:容器共享宿主操作系统的内核,占用较少的系统资源。
  • 可移植性:容器可以在不同的环境中运行,包括开发、测试和生产环境。

Docker 历史

Docker 起源于 2013 年。Docker 是一个开源的应用容器引擎,基于 Go 语言开发,Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的系统


Docker 优点

Docker带来了许多好处,包括:

  • 快速交付应用程序:Docker可以加速打包、测试和发布过程,缩短开发周期。
  • 复杂环境管理:Docker解决了不同软件运行环境的兼容性和依赖问题,确保开发、测试和生产环境的一致性。
  • 轻量级:对于宿主操作系统来说,从狭义上看一个Docker容器只是一个进程,一个系统可以运行多个容器。


服务、测试环境、测试机对应图

在典型的开发和部署流程中,不同的环境需要不同的设置。Docker可以帮助管理这些环境,确保它们保持一致,从而减少问题的发生。


Docker 与虚拟机的区别

Docker与传统虚拟机有很大的区别:

  • 容器与容器之间只是进程的隔离,而虚拟机是完全的资源隔离。
  • Docker容器启动快速,通常在秒级或更短的时间内,而虚拟机可能需要分钟级的时间。
  • 容器共享宿主操作系统的内核,而虚拟机使用完全独立的内核。

Docker适用于一些特定的使用场景,但也有一些限制,需要根据具体情况选择使用。


Docker 架构

Docker采用了客户端-服务器架构,包括以下组件:

  • Docker客户端:与用户交互的命令行工具。
  • Docker主机:运行Docker守护进程的服务器。
  • Docker守护进程:管理容器的后台服务。
  • Docker镜像:容器的模板,包含应用程序和其依赖项。
  • Docker容器:Docker镜像的运行实例。


Docker 在 CI/CD 中的应用

Docker在持续集成和持续交付(CI/CD)中扮演着重要的角色,它提供了一种标准化和可复制的环境,以加速构建、测试和部署过程。以下是Docker在CI/CD中的应用:

  • 构建和打包:使用Docker容器来构建应用程序,确保构建环境的一致性。
  • 自动化测试:在Docker容器中运行测试,包括单元测试、集成测试和端到端测试。
  • 部署到生产环境:使用Docker容器将应用程序和其依赖项打包,然后在生产环境中快速部署。

这些应用可以帮助团队实现快速、可重复的交付过程,降低错误风险,提高开发和运维效率。


概念

在使用Docker时,有一些重要的概念需要了解:

  • Docker镜像:Docker Images,Docker容器的模板,包含应用程序和其依赖项。每一个镜像都可能依赖一个或多个下层的镜像组成的另一个镜像,AUFS 文件系统。
  • Docker仓库:Docker Registry,用于存储和分享Docker镜像的地方。
  • Docker容器:Docker Containers,Docker镜像的运行实例。

Docker 的安装与配置


简介

  • Docker 支持多种操作系统平台,Windows, Linux, macOS
  • 注意:推荐在 Linux 上使用。


安装

Linux 发行版 CentOS 安装方法

# 切换管理员权限
su root

# 安装 Docker 依赖
yum install -y yum-utils device-mapper-persistent-data lvm2

# 配置依赖下载源
yum-config-manager --add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 安装 docker
yum makecache fast && yum -y install docker-ce

常用操作

  • 启动:systemctl start docker
  • 重启:systemctl restart docker
  • 开机自启动:systemctl enable docker
  • 运行状态:systemctl status docker

Docker 加速器配置

  • 配置 registry-mirrors
  • 推荐从阿里云、华为云等地方获取国内镜像地址
# 添加 registry-mirrors
vim /etc/docker/daemon.json

# 内容
{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}

# 重载 docker 的配置文件
systemctl daemon-reload

# 重启 Docker
systemctl restart docker

## 查看配置
docker info
docker version

从hello world 开始

docker run hello-world

Docker 容器管理


容器是什么

容器是您机器上的沙盒进程,与主机上的所有其他进程隔离。这种隔离利用了内核命名空间和 cgroups,这些特性已经在 Linux 中存在了很长时间。 Docker 致力于使这些功能变得平易近人且易于使用。总而言之,一个容器: 是image 的可运行实例。您可以使用 DockerAPI 或 CLI 创建、启动、停止、移动或删除容器。 可以在本地机器、虚拟机上运行或部署到云端。 是可移植的(可以在任何操作系统上运行)。 与其他容器隔离并运行自己的软件、二进制文件和配置。


Docker 命令全貌


容器的运行

  • 运⾏容器:docker run -d --name=busybox busybox:latest ping 114.114.114.114
  • 查看运⾏的容器:docker psdocker ps -a
  • 查看容器中运⾏的进程:docker top busybox
  • 查看资源占⽤:docker stats busybox
  • 容器:docker start/restart/stop/kill busybox
  • 暂停容器:docker pause/unpause busybox
  • 强制删除容器:docker rm -f busybox

容器管理

  • 执⾏命令:docker exec -it busybox ls
  • 复制⽂件:docker cp busybox:/etc/hosts hosts
  • 查看容器⽇志:docker logs -f busybox
  • 查看容器/镜像的元信息:docker inspect busybox
  • 查看容器内⽂件结构:docker diff busybox

Docker 镜像管理


Docker 镜像结构

Docker 容器化采用联合文件系统,达到底层的镜像复用的效果。


镜像管理

  • 查看所有镜像:docker images
  • 搜索镜像:docker search busybox
  • 拉取下载:docker pull busybox:latest
  • 导出:docker save busybox > busybox.tar
  • 导⼊:docker load < busybox.tar
  • 删除:docker rmi busybox:latest
  • 更改镜像名:docker tag busybox:latest busybox:test
  • 查看镜像创建历史:docker history busybox

搭建 Web 服务器 Nginx


Nginx 简介

  • Nginx(发音同 engine x)是一个异步的 Web 服务器,主要提供 Web 服务、反向代理、负载均衡和 HTTP 缓存功能。由 Igor Sysoev 创建于 2004 年,使用 C 语言开发。

运行 Nginx 容器

  • 拉取:docker pull nginx:latest
  • 运行:docker run -d --name nginx -p 8088:80 nginx:latest
  • 挂载目录:docker run -d --name nginx1 -p 8089:80 -v ${PWD}/html:/usr/share/nginx/html nginx:latest

搭建数据库服务 MySQL


MySQL 简介

  • MySQL 是最流行的开源关系型数据库。
  • 可以访问 MySQL 镜像的官方网站:https://hub.docker.com/_/mysql 查看更多信息。

部署 MySQL 数据库

docker pull mysql:8.0.26

docker run -d -p 3306:3306 --name mysql1 \
  --privileged=true -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0.26

ps: --privileged=true 的作用,使用特权模式启动容器


MySQL 基本命令

docker exec -it mysql1 bash
mysql -u root -p 123456 连接Mysql
alter user 'admin'@'localhost' identified by '123456'; 增加新用户
create database my_data; 创建数据库
show databases; 显示数据库
drop database my_data; 删除数据库
use my_data; 连接数据库
select version(); 显示MYSQL的版本
select now(); 显示当前时间

连接数据库

  • phpMyAdmin、DataGrip、Navicat、HeidiSQL
  • 推荐比较好用免费的 Mysql 数据库管理工具 HeidiSQL
  • 官网:https://www.heidisql.com/download.php
  • 网盘链接:https://pan.baidu.com/s/1zANZdB1cjH3KkUy4XnEUwQ 提取码:sf09

搭建持续集成平台 Jenkins


Jenkins 简介

  • Jenkins 是开源 CI&CD 软件领导者,提供持续集成和持续交付服务,有超过 1000 个插件来支持构建、部署、自动化,满足任何项目的需要。

部署 Jenkins

  • Docker hub:https://hub.docker.com/r/jenkins/jenkins/
  • 运行:docker run -d --name=jenkins -p 8080:8080 jenkins/jenkins
  • 查看默认密码:docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword
  • 挂载目录:chmod 777 jenkins
  • 运行:docker run --name jenkins -d -p 8080:8080 -p 50000:50000 -v ${PWD}/jenkins:/var/jenkins_home jenkins/jenkins

ps:如何在 jenkins 容器中使用 Docker --privileged=true --volumes-from=/var/run/docker.sock


搭建项目管理平台 Jira


Jira 简介

  • Jira 是 Atlassian 公司出品的项目与事务跟踪工具,被广泛应用于缺陷跟踪、客户服务、需求收集、流程审批、任务跟踪、项目跟踪和敏捷管理等工作领域。
  • 可以访问 Jira 镜像的介绍网站:https://hub.docker.com/r/atlassian/jira-software 查看更多信息。

部署数据库

docker run -d -p 3306:3306 --name mysql_jira -u root -e MYSQL_ROOT_PASSWORD=ceshiren.com mysql:5.7

配置 mysql 数据库

# 连接数据库
docker run -it --link mysql_jira:mysql --rm mysql sh -c 'exec mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD"'
# 创建数据库
create database jira default character set utf8 collate utf8_bin;
# 创建用户
create user `jira`@`%` identified by 'jira';grant all on *.* to `jira`@`%` with grant option;
# 添加用户
alter user 'jira'@'%' identified with mysql_native_password by 'jira';

启动 jira 实例

docker run -d -p 8080:8080 --name jira --restart always --privileged=true -u root cptactionhank/atlassian-jira-software:7.11.1


  • Testlink 是基于 WEB 的测试用例管理系统,主要功能是:测试项目管理、产品需求管理、测试用例管理、测试计划管理、测试用例的创建、管理和执行,并且还提供了统计功能。
  • 可以访问 Testlink 镜像的介绍网站:https://hub.docker.com/r/bitnami/testlink/ 查看更多信息。

部署数据库

  • Testlink 服务存储数据依赖数据库服务,所以需要先搭建一个数据库。
  • 同时数据库和 Testlink 服务之间访问需要网络互相通畅,所以需要建立一个容器网络。

  • 容器网络:docker network create testlink
  • 运行数据库:
docker run -d --name mariadb \
-e MARIADB_ROOT_PASSWORD=mariadb \
-e MARIADB_USER=bn_testlink \
-e MARIADB_PASSWORD=bn_testlink \
-e MARIADB_DATABASE=bitnami_testlink \
--net testlink -v ${PWD}/mariadb:/bitnami bitnami/mariadb:10.3.22

  • 运行 Testlink:
  • 默认用户名:user,默认密码:bitnami
docker run -d -p 8080:8080 \
-p 8443:8443 --name testlink \
-e TESTLINK_DATABASE_USER=bn_testlink \
-e TESTLINK_DATABASE_PASSWORD=bn_testlink \
-e TESTLINK_DATABASE_NAME=bitnami_testlink --net testlink \
-v ${PWD}/testlink:/bitnami bitnami/testlink-archived

访问

浏览器内访问:http://你的 IP 地址:端口

  • 8080 和 8443 为 HTTP/HTTPS 访问端口。
  • 默认用户:user,默认密码:bitnami

Docker镜像构建


Docker 容器镜像制作方式

  • 在日常的工作中,常常需要制作自己的项目的镜像,一般通过以下两种方式制作镜像:Docker commit、Dockerfile

Docker commit

  • Docker commit 一般用做从一个运行状态的容器来创建一个新的镜像。定制镜像应该使用 Dockerfile 来完成。默认 commit 镜像,对外不可解释,不方便排查问题,可维护性差。
  • docker commit 容器名 新镜像名:tag

Docker 容器镜像制作命令

  • 忽略文件:.dockerignore
  • 指定文件:docker build -f
  • 添加标签:docker build -t
  • 不使用缓存:docker build --no-cache
  • 构建时变量:docker build --build-arg
    • ARG 指令变量

Flask 应用

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, Docker!'
FROM python:3.8-slim-buster

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt

COPY . .

CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]


Docker 制作容器镜像实战

  • 构建:docker build -f Dockerfile-build -t app:v1.0
  • 启动:docker run --name app -p 5000:5000 app:v1.0

Docker-compose


Docker-compose 简介

  • Docker-compose 是用于定义和运行多容器的 Docker 应用程序的工具。通过 Compose,可以使用 YAML 文件来配置应用程序的服务。
  • Compose 的使用一般分为三步:
    1. 使用 Dockerfile 定义应用程序的环境,以便可以在任何地方复制它。
    2. 在 docker-compose.yml 中定义组成应用程序的服务,以便它们可以在隔离的环境中一起运行。
    3. 运行 docker-compose up,然后 Compose 启动并运行您的整个应用程序。

Docker-compose 安装

  • macOS、Windows 系统使用的 Docker Desktop 默认已经安装。
  • Linux 系统:
    • https://github.com/docker/compose/releases
      curl "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
      
    • 更改权限:chmod +x /usr/local/bin/docker-compose
    • 查看版本:docker-compose version

安装方式2: yum install epel-release yum install docker-compose


Docker-compose 演示

  • 通过一个 Python web 小实例来演示 Docker-compose 的功能。

创建 app.py

import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)

创建 requirements.txt

flask
redis

创建Dockerfile

FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]

创建docker-compose.yml

services:
  web:
    build: .
    ports:
      - "8000:5000"
  redis:
    image: "redis:alpine"


Docker-compose 常用命令

  • 查看配置:docker-compose config
  • 后台启动:docker-compose up -d
  • 构建镜像:docker-compose build
  • 下载镜像:docker-compose pull
  • 运行的:docker-compose ps
  • 进程:docker-compose top
  • 启动:docker-compose start
  • 停止:docker-compose stop

Docker Compose 实战练习


Docker 私有镜像仓库


docker registry 架构


docker registry 常用命令

# 官方提供的hub
docker run -d -p 5000:5000 --restart=always --name registry registry:2
docker run -d -p 5000:5000 --restart=always --name registry -v $PWD/registry:/var/lib/registry registry:2
docker pull ubuntu:16.04
docker tag ubuntu:16.04 localhost:5000/my-ubuntu
docker push localhost:5000/my-ubuntu
curl http://127.0.0.1:5000/v2/_catalog

docker pull localhost:5000/my-ubuntu

一般公司采取 https://demo.goharbor.io/

````


### Docker 在测试中的经典使用

### 部署分布式 UI 自动化测试环境

方式1:

```bash

docker network create selenium


docker run --name hub --net=selenium -d -p 8442-8444:4442-4444 selenium/hub:4.9.0-20230421

docker run -d \
  --net=selenium \
  --name node1 \
  -p 5901:5900 \
  -e SE_EVENT_BUS_HOST=hub \
  -e SE_NODE_MAX_SESSIONS=10 \
  -e SE_NODE_OVERRIDE_MAX_SESSIONS=true \
  -e SE_EVENT_BUS_PUBLISH_PORT=4442 \
  -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \
  selenium/node-chrome:4.9.0-20230421


docker run -d \
  --net=selenium \
  --name node2 \
  -p 5902:5900 \
  -e SE_EVENT_BUS_HOST=hub \
  -e SE_NODE_MAX_SESSIONS=10 \
  -e SE_NODE_OVERRIDE_MAX_SESSIONS=true \
  -e SE_EVENT_BUS_PUBLISH_PORT=4442 \
  -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \
  selenium/node-chrome:4.9.0-20230421

docker run -d \
  --net=selenium \
  --name node3 \
  -p 5903:5900 \
  -e SE_EVENT_BUS_HOST=hub \
  -e SE_NODE_MAX_SESSIONS=10 \
  -e SE_NODE_OVERRIDE_MAX_SESSIONS=true \
  -e SE_EVENT_BUS_PUBLISH_PORT=4442 \
  -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \
  selenium/node-firefox:4.14.1-20231020

方式2:docker-compose

version: "3"
services:
  chrome:
    image: selenium/node-chrome:4.9.0-20230421
    shm_size: 1gb
    depends_on:
      - selenium-hub
    environment:
      - SE_NODE_MAX_SESSIONS=10
      - SE_NODE_OVERRIDE_MAX_SESSIONS=true
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443

  chrome1:
    image: selenium/node-chrome:4.9.0-20230421
    shm_size: 1gb
    depends_on:
      - selenium-hub
    environment:
      - SE_NODE_MAX_SESSIONS=10
      - SE_NODE_OVERRIDE_MAX_SESSIONS=true
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443

  firefox:
    image: selenium/node-firefox:4.14.1-20231020
    shm_size: 1gb
    depends_on:
      - selenium-hub
    environment:
      - SE_NODE_MAX_SESSIONS=10
      - SE_NODE_OVERRIDE_MAX_SESSIONS=true
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443

  selenium-hub:
    image: selenium/hub:4.9.0-20230421
    container_name: selenium-hub
    ports:
      - "8442:4442"
      - "8443:4443"
      - "8444:4444"

测试代码:

import random

import pytest
from selenium import webdriver
from selenium.webdriver.chromium.options import ChromiumOptions
from selenium.webdriver.firefox.options import Options


@pytest.mark.parametrize("count", [1, 2, 3])
def test_browser(count):
    options = ChromiumOptions()
    ff_options = Options()
    print(count)
    options.add_argument('--ignore-ssl-errors=yes')
    options.add_argument('--ignore-certificate-errors')
    driver = webdriver.Remote('http://192.168.0.104:8444/wd/hub', options=random.choice([ff_options,options]))
    driver.get('https://www.baidu.com')
    print(driver.title)
    print(driver.page_source)
    driver.quit()