我的docker随笔27:基于容器的sqlite测试

需求:
sqlite 常用于嵌入式平台,本文使用容器进行测试。选用环境有 nodejs 和 python,主要目的是测试在容器运行的情况,及数据共享。测试代码源自网络,但有修改。

nodejs 环境

创建工程目录。
运行容器:

1
2
3
sudo docker run -itd --rm --name node -v $PWD:/home/node node:alpine sh

sudo docker exec -it node sh

查看容器的 node 版本为 14.2.0,在宿主机上安装指定的版本:

1
2
sudo npm i -g n
sudo n 14.2.0

安装 sqlite:

1
sudo npm install sqlite3

写数据库核心代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
注1:node为异步,不能按顺序创建表、插入数据,可能会提示表不存在。
注2:
*/
var sqlite3 = require('sqlite3').verbose();

var db;
db = new sqlite3.Database("db.db", function(err) {
if (err) throw err;
});

console.log("db: ", db)
db.run(`create table IF NOT EXISTS user (id INT,name VARCHAR,password VARCHAR)`, function(
err
) {
if (err) throw err;
console.log("Create Table Success!");
});

// Run Insert Data
db.run(`insert into user values (666,"admin","admin")`, function(err) {
if (err) throw err;
console.log("Insert Data Success!");
});

db.close(function(err) {
if (err) throw err;
});

注意,由于 nodejs 是异步的,所以可能会提示 user 表不存在,多次执行即可。本文仅演示,不做实践指导。

查询数据库核心代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var sqlite3 = require('sqlite3').verbose();

var db;
db = new sqlite3.Database("db.db", function(err) {
if (err) throw err;
});

function show() {
console.log("inside....")
db.all("select * from user", function(err, rows) {
if (err) throw err;
console.log(rows);
});

setTimeout(show, 1000);
}

show();

/*
db.close(function(err) {
if (err) throw err;
});
*/

解释:间隔 1 秒查询数据库并打印数据。

测试结论:
宿主机写、读数据库,通过。
宿主机写数据库,容器读数据库,通过。
容器写数据库,宿主机查询,失败。在容器中执行提示段错误Segmentation fault。尝试在纯 docker 目录中执行,亦然。

nodejs arm 环境

此处仅描述环境的搭建。需求:在 arm 平台实现 nodejs 容器,内含 koa、sqlite3。
在 x86 运行 arm 容器。

1
2
3
4
docker pull arm32v7/node:10-slim

docker run -itd --rm -v $PWD:/home/node -p 3000:3000 --name nodejsbuild arm32v7/node:10-slim sh
docker exec -it nodejsbuild sh

安装:

1
npm install sqlite3

出错:

1
2
3
4
5
6
7
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! sqlite3@4.2.0 install: `node-pre-gyp install --fallback-to-build`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the sqlite3@4.2.0 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

分析:

1
2
3
4
5
6
7
8
9
node-pre-gyp WARN Using needle for node-pre-gyp https download 
node-pre-gyp WARN Tried to download(403): https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.2.0/node-v64-linux-arm.tar.gz
node-pre-gyp WARN Pre-built binaries not found for sqlite3@4.2.0 and node@10.20.1 (node-v64 ABI, glibc) (falling back to source compile with node-gyp) // !! arm 平台没有预编译,需要从源码安装
gyp ERR! find Python // !! 未安装python
gyp ERR! find Python Python is not set from command line or npm configuration
gyp ERR! find Python Python is not set from environment variable PYTHON

gyp ERR! build error
gyp ERR! stack Error: not found: make // !! 未安装编译所需工具

解决:

1
2
3
apt-get install python3
ln -s /usr/bin/python3 /usr/bin/python // 做链接
apt-get install build-essential

制作备忘:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cd /home/latelee/nodejs/node_arm/node
docker build -t nodejsapp .

docker tag nodejsapp registry.cn-hangzhou.aliyuncs.com/latelee/nodejsapp:armweb
docker push registry.cn-hangzhou.aliyuncs.com/latelee/nodejsapp:armweb

docker run -itd --rm -p 9000:3000 --name nodejsapp1 nodejsapp

docker run -itd --rm -p 3000:3000 --name nodejsapp1 registry.cn-hangzhou.aliyuncs.com/latelee/nodejsapp:armweb

docker load -i nodejsapp.img
docker run -itd --rm -p 3000:3000 -v /mnt/data:/mnt/data --name nodejsapp1 registry.cn-hangzhou.aliyuncs.com/latelee/nodejsapp:armweb


docker run -itd --rm -p 3000:3000 -v /mnt/aaa/nodejsapp/node:/home/node -v /mnt/data:/mnt/data --name nodejs nodebase

docker run -itd --rm -p 3000:3000 -v /mnt/data:/mnt/data --name nodejsapp nodejsapp

docker run -itd --rm -p 9000:3000 -v $PWD/data:/mnt/data --name nodejsapp nodejsapp
(注:导出3000端口,方便其它主机访问。挂载/mnt/data以便访问数据库。

python 环境

运行容器:

1
2
docker run -itd --rm --name python -v $PWD:/home/python python:3.5-slim-stretch sh
docker exec -it python sh

注:该镜像已经包含了 sqlite3 库,无须额外安装。

写数据库核心代码:

1
2
3
4
5
6
7
8
9
import sqlite3

conn = sqlite3.connect("db.db")
cursor = conn.cursor()
cursor.execute("insert into user values (777,\"python11\",\"adminpython\")")

cursor.close()
conn.commit()
conn.close()

查询数据库:

1
2
3
4
5
6
7
8
9
10
11
import sqlite3

conn = sqlite3.connect("db.db")
cursor = conn.cursor()
cursor.execute("select * from user")
values = cursor.fetchall()
print(values)

cursor.close()
conn.commit()
conn.close()

结论:
同上,但在容器中可以写数据库。
另外,python 容器中写数据库,nodejs 容器中查询数据库,正常。

小结

sqlite 只需数据库文件即可。适用于小型系统。本文测试发现 nodejs 容器无法写数据库(包括创建数据表)。
只要保证数据库文件相同,跨容器可以操作数据库。