软件工程相关环境配置

软件工程相关环境配置

Contents

Docker

安装

Mac 链接Windows 链接 下载安装程序,按照教程安装。

以 Mac 为例,安装完成打开后,在终端输入命令,可以看到 Docker 版本:

$ docker --version
Docker version 20.10.13, build a224086

镜像

考虑到科学上网等问题,建议为 Docker 添加国内镜像。

在 Docker 中点击 Preference...,选择 Docker Engine 选项卡,在其中添加一项 registry-mirrors,填入一项网易镜像地址 http://hub-mirror.c.163.com(其他镜像也可以自行添加):

{
  "registry-mirrors": [
    "http://hub-mirror.c.163.com"
  ],
  "builder": {
    "gc": {
      "enabled": true,
      "defaultKeepStorage": "20GB"
    }
  },
  "debug": true,
  "experimental": false
}

之后点击 Apply & Restart 按钮,在终端查看 Docker 信息:

$ docker info
...
 Insecure Registries:
  hubproxy.docker.internal:5000
  127.0.0.0/8
 Registry Mirrors:
  http://hub-mirror.c.163.com/
...

可以看到镜像添加成功。

测试使用

以样例仓库 monolithic-example 为例,这是一个以 Django 为后端,React 为前端,前端通过 npm run build 预先构建得到静态 .js 文件用于 Django 的路由的前后端结合方式。

首先克隆仓库:

git clone git@git.tsinghua.edu.cn:SEG/example/monolithic-example.git

按照 README.md 中所述构建并运行 Docker(注意添加端口):

docker build -t something .
docker run -p 80:80 --rm something

然后在浏览器中输入 http://0.0.0.0/metrics,我们将看到如下网页:

# HELP python_gc_objects_collected_total Objects collected during gc
# TYPE python_gc_objects_collected_total counter
python_gc_objects_collected_total{generation="0"} 969.0
python_gc_objects_collected_total{generation="1"} 850.0
python_gc_objects_collected_total{generation="2"} 231.0
...

这也就说明我们的 Docker 构建和运行成功了。

如果需要停止容器,可以新开启一个终端,使用:

docker ps -a

查找对应的 CONTAINER_ID,并使用:

docker stop CONTAINER_ID

来停止容器。

开发环境

使用下列命令在 conda 中开启一个名为 example 的新虚拟环境:

conda create -n example python=3.8.5

安装依赖:

pip install -r requirements_dev.txt

如果出现了包安装错误,可考虑到 链接 安装对应的软件,并添加对应的 PATH 变量,以 Mac 为例:/Library/PostgreSQL/14/bin

Redis

Docker 中使用

新开一个文件夹 redis-example,其中添加一个 Dockerfile 文件:

FROM redis:latest

EXPOSE 6379

COPY redis.conf /usr/local/etc/redis/redis.conf
CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]

新建 redis.conf 文件,来源于 链接,可能需要修改的几个点是:

bind 127.0.0.1 -::1 # 需要注释才可以外部访问
# requirepass foobared # 取消注释 自己设置密码 建议设置
appendonly no # 设置为 yes 使得 redis 持久化
dir ./ # 设置本地数据库存放目录 可设置为形如 /data/ 并配合平台的挂载功能使用

运行下列命令以构建和运行容器:

docker build -t redis .
docker run -p 6379:6379 --rm redis

使用安装了 redis 包的 Python,运行脚本 test.py

import redis

pool = redis.ConnectionPool(host='127.0.0.1', port=6379, password='foobared')
r = redis.Redis(connection_pool=pool)
r.set('Age', 18)
print(r.get('Age'))

可以发现输出即为:

b'18'

符合预期。

后端配置

requirements.txt 中添加一行:

redis==4.1.4

重新安装依赖并重新 build 容器。

SECoder 使用

由于 Redis 自定义配置文件需要手动指定,所以需要考虑使用自定义镜像。

上传镜像

首先到 Docker Hub 上注册账号,在本地 Docker 登录后,使用上面类似的命令构建镜像并推送到 Docker Hub:

docker build -t <username>/redis .
docker push <username>/redis

其中 <username> 建议填写为注册的用户名(防止冲突)。

SECoder 部署与持久卷配置

在 SECoder 的部署管理界面,选择添加容器,填写自定义的容器名(如 redis)和镜像(即上面的 <username>/redis:latest),等待构建。

注:

  • 如果不想这么麻烦,也可以直接使用我上传的镜像 wzf2000/redis,密码为 foobared,数据目录为 /data/

  • 如果需要自定义配置,比如数据目录等,建议还是推送一下镜像

添加一个持久存储,可命名为 redis-data

在刚添加的容器中挂载刚添加的持久存储,挂载点填写为上面配置中的 dir 值(如 /data)。

注意开启对应的端口。

内网连接测试

等待容器重启后,打开一个带有 Python 环境的其他容器(比如后端容器)的终端,如果没有安装 redis 包,则先:

pip install redis

然后输入 python 进入 Python 的 CLI,依次输入以下命令测试:

import redis
pool = redis.ConnectionPool(host='<your-local-address>', port=6379, password='foobared')
r = redis.Redis(connection_pool=pool)
r.set('Age', 18)
print(r.get('Age'))

其中 <your-local-address> 替换为 Redis 容器的内网地址(形如 <container-name>.<group-name>.secoder.local)。

我们将看到以下反馈,代表连接成功(这边可以重启 Redis 容器,确认 get 依然成功):

b'18'

Elastic Search

Docker 中使用

新开一个文件夹 es-example,其中添加一个 Dockerfile 文件:

FROM elasticsearch:7.17.1

COPY elasticsearch.yml /usr/share/elasticsearch/config

# expose the default Elasticsearch port
EXPOSE 9200 9300

新建配置文件 elasticsearch.yml(其中 path.data 对应地址可作为存储卷挂载):

# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
#
cluster.name: elasticsearch
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
#
node.name: test
#
# Add custom attributes to the node:
#
#node.attr.rack: r1
#
# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
#
path.data: /usr/share/elasticsearch/data
#
# Path to log files:
#
path.logs: /usr/share/elasticsearch/logs
#
# ----------------------------------- Memory -----------------------------------
#
# Lock the memory on startup:
#
#bootstrap.memory_lock: true
#
# Make sure that the heap size is set to about half the memory available
# on the system and that the owner of the process is allowed to use this
# limit.
#
# Elasticsearch performs poorly when the system is swapping the memory.
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: 0.0.0.0
#
# Set a custom port for HTTP:
#
http.port: 9200
#
# For more information, consult the network module documentation.
#
# --------------------------------- Discovery ----------------------------------
#
# Pass an initial list of hosts to perform discovery when this node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
#
#discovery.seed_hosts: ["host1", "host2"]
#
# Bootstrap the cluster using an initial set of master-eligible nodes:
#
#cluster.initial_master_nodes: ["node-1", "node-2"]
#
# For more information, consult the discovery and cluster formation module documentation.
#
# ---------------------------------- Gateway -----------------------------------
#
# Block initial recovery after a full cluster restart until N nodes are started:
#
#gateway.recover_after_nodes: 3
#
# For more information, consult the gateway module documentation.
#
# ---------------------------------- Various -----------------------------------
#
# Require explicit names when deleting indices:
#
#action.destructive_requires_name: true
discovery.type: single-node

运行下列命令以构建和运行容器:

docker build -t elasticsearch .
docker run -p 9200:9200 -p 9300:9300 --rm elasticsearch

之后在浏览器中输入 http://localhost:9200/ 即可看到:

{
  "name" : "test",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "OIu1eIjgTwSIzSyIxQZW0g",
  "version" : {
    "number" : "7.17.1",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "e5acb99f822233d62d6444ce45a4543dc1c8059a",
    "build_date" : "2022-02-23T22:20:54.153567231Z",
    "build_snapshot" : false,
    "lucene_version" : "8.11.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

后端配置

requirements.txt 中添加一行:

elasticsearch==7.17.1

重新安装依赖并重新 build 容器。

SECoder 使用

由于 ES 中的配置文件目录下文件较多,直接挂载配置项难以保证剩余文件正常使用,所以需要考虑使用自定义镜像。

上传镜像

首先到 Docker Hub 上注册账号,在本地 Docker 登录后,使用上面类似的命令构建镜像并推送到 Docker Hub:

docker build -t <username>/elasticsearch .
docker push <username>/elasticsearch

其中 <username> 建议填写为注册的用户名(防止冲突)。

SECoder 部署与持久卷配置

在 SECoder 的部署管理界面,选择添加容器,填写自定义的容器名(如 elasticsearch)和镜像(即上面的 <username>/elasticsearch:latest),等待构建。

注:

  • 如果不想这么麻烦,也可以直接使用我上传的镜像 wzf2000/elasticsearch,对应的配置即为上述所写。

  • 如果需要自定义配置,比如数据目录等,建议还是推送一下镜像

添加一个持久存储,可命名为 es-data

在刚添加的容器中挂载刚添加的持久存储,挂载点填写为上面配置中的 path.data 值(如 /usr/share/elasticsearch/data)。

注意开启对应的端口。

内网连接测试

等待容器重启后,打开一个带有 Python 环境的其他容器(比如后端容器)的终端,如果没有安装 elasticsearch 包,则先:

pip install elasticsearch==7.17.1

然后输入 python 进入 Python 的 CLI,依次输入以下命令测试:

from elasticsearch import Elasticsearch
from elasticsearch import AsyncElasticsearch
client = Elasticsearch("http://<your-local-address>:9200")
client.search(index='*')

其中 <your-local-address> 替换为 ES 容器的内网地址(形如 <container-name>.<group-name>.secoder.local)。

我们将看到以下反馈,代表连接成功:

{'took': 0, 'timed_out': False, '_shards': {'total': 0, 'successful': 0, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 0, 'relation': 'eq'}, 'max_score': 0.0, 'hits': []}}

MySQL/MariaDB

Docker 中使用

直接使用 gjz010/mariadb:latest 作为镜像即可,注意查看初始日志记录初始密码,方便后续的登录调试。

后端配置

requirements.txt 中添加一行:

pymysql==1.0.2

重新安装依赖并重新 build 容器。

SECoder 使用

SECoder 部署

首先创建一个容器,容器名自取,镜像名为 gjz010/mariadb:latest

在端口处开放端口 3306,等待容器重启完毕后,打开容器的日志,在其中查找如下字段:

...
GENERATED ROOT PASSWORD: XXXXXX
...

将后面的 XXXXX 记录下来,即为自动随机生成的 root 账户初始密码。

持久卷部署

随后打开容器的终端,利用刚刚得到的密码登录 MySQL:

$ mysql -uroot -p
Enter password:

输入命令确定数据存储位置:

MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE 'datadir';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| datadir       | /var/lib/mysql/ |
+---------------+-----------------+
1 row in set (0.001 sec)

可知数据存储在 /var/lib/mysql/ 下。

通过持久卷存储挂载到此目录下,然后再次使用密码进入容器登录 MySQL 进行测试。

尝试创建一个数据库:

MariaDB [(none)]> create database test;
Query OK, 1 row affected (0.006 sec)

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.002 sec)

完成后重启容器(可通过任意修改端口,注意操作不要太快,否则可能导致出现两个容器抢占存储卷),重新进入容器,登录 MySQL 测试:

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.003 sec)

可以看到数据得以保存。

内网连接测试

打开一个带有 Python 环境的其他容器(比如后端容器)的终端,如果没有安装 pymysql 包,则先执行:

pip install pymysql

然后输入 python 进入 Python 的 CLI,依次输入以下命令测试:

import pymysql
db = pymysql.connect(host='<your-local-address>',
                     user='root',
                     password='<password>',
                     database='test')
cursor = db.cursor()
cursor.execute("DROP TABLE IF EXISTS EMPLOYEE")
sql = """CREATE TABLE EMPLOYEE (
         FIRST_NAME  CHAR(20) NOT NULL,
         LAST_NAME  CHAR(20),
         AGE INT,  
         SEX CHAR(1),
         INCOME FLOAT )"""
cursor.execute(sql)
db.close()

其中 <your-local-address> 替换为 MySQL 容器的内网地址(形如 <container-name>.<group-name>.secoder.local),<password> 替换为之前得到的初始密码(或者自行修改后的密码)。

之后重新进入 MySQL 容器的终端,进行测试:

MariaDB [(none)]> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [test]> show tables;
+----------------+
| Tables_in_test |
+----------------+
| EMPLOYEE       |
+----------------+
1 row in set (0.000 sec)

MariaDB [test]> desc EMPLOYEE;
+------------+----------+------+-----+---------+-------+
| Field      | Type     | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+-------+
| FIRST_NAME | char(20) | NO   |     | NULL    |       |
| LAST_NAME  | char(20) | YES  |     | NULL    |       |
| AGE        | int(11)  | YES  |     | NULL    |       |
| SEX        | char(1)  | YES  |     | NULL    |       |
| INCOME     | float    | YES  |     | NULL    |       |
+------------+----------+------+-----+---------+-------+
5 rows in set (0.001 sec)

可以发现,数据表建立成功。

单元测试

待补充。

 

点赞 13

No Comments

Add your comment