项目实战
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 ps
,docker 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 inspect -f '\{\{\.Id\}\}\' busybox
- Inspect 语法参考
- 格式化输出:
- 查看容器内⽂件结构:
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
TestLink 简介
- Testlink 是基于 WEB 的测试用例管理系统,主要功能是:测试项目管理、产品需求管理、测试用例管理、测试计划管理、测试用例的创建、管理和执行,并且还提供了统计功能。
- 可以访问 Testlink 镜像的介绍网站:https://hub.docker.com/r/bitnami/testlink/ 查看更多信息。
部署数据库
- 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
- 运行 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 的使用一般分为三步:
- 使用 Dockerfile 定义应用程序的环境,以便可以在任何地方复制它。
- 在 docker-compose.yml 中定义组成应用程序的服务,以便它们可以在隔离的环境中一起运行。
- 运行 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
- https://github.com/docker/compose/releases
安装方式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()