话不多说上干货:
一、安装mysql数据库,并且建立相关表
在本地主机上安装mysql数据库,并且建立一个名为docker的数据库,在数据库中建立两个数据表分别为container_auto和container_user,分别代表自动生成的秘钥和用户自己输入的秘钥,两个表的字段都为id和passphrase,如下
mysql> create table container_auto(
> id char(20) not null primary key,
> passphrase char(40) not null);
container_user和container_auto结构一样
二、搭建docker编译环境
搭建教程,并在/go/src/github.com/docker/docker下修改源码,最后编译
三、修改源码
在/go/src/github.com/docker/docker修改
mkdir crypt
vi crypt/mysql.go
package crypt
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
func InsertUser(id string, passphrase string) {
db, err := sql.Open("mysql", "root:zhang@tcp(127.0.0.1:3306)/docker?charset=utf8")
checkErr(err)
stmt, err := db.Prepare(`INSERT container_user (id,passphrase) values (?,?)`)
checkErr(err)
_, err = stmt.Exec(id, passphrase)
checkErr(err)
}
func InsertAuto(id string, passphrase string) {
db, err := sql.Open("mysql", "root:zhang@tcp(127.0.0.1:3306)/docker?charset=utf8")
checkErr(err)
stmt, err := db.Prepare(`INSERT container_auto (id,passphrase) values (?,?)`)
checkErr(err)
_, err = stmt.Exec(id, passphrase)
checkErr(err)
}
func Remove(id string) {
db, err := sql.Open("mysql", "root:zhang@tcp(127.0.0.1:3306)/docker?charset=utf8")
checkErr(err)
stmt_auto, err := db.Prepare(`DELETE FROM container_auto WHERE id=?`)
checkErr(err)
_, err = stmt_auto.Exec(id)
checkErr(err)
stmt_user, err := db.Prepare(`DELETE FROM container_user WHERE id=?`)
checkErr(err)
_, err = stmt_user.Exec(id)
checkErr(err)
}
func QueryUser(id string) string {
db, err := sql.Open("mysql", "root:zhang@tcp(127.0.0.1:3306)/docker?charset=utf8")
checkErr(err)
var password string
rows, err := db.Query(`SELECT passphrase FROM container_user WHERE id=?`, id)
checkErr(err)
for rows.Next() {
err := rows.Scan(&password)
checkErr(err)
}
return password
}
func QueryAuto(id string) string {
db, err := sql.Open("mysql", "root:zhang@tcp(127.0.0.1:3306)/docker?charset=utf8")
checkErr(err)
var password string
rows, err := db.Query(`SELECT passphrase FROM container_auto WHERE id=?`, id)
checkErr(err)
for rows.Next() {
err := rows.Scan(&password)
checkErr(err)
}
return password
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
vi crypt/crypt.go
package crypt
import (
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
func RandStringBytes(n int) string {
const letterBytes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
b := make([]byte, n)
for i := range b {
b[i] = letterBytes[rand.Intn(len(letterBytes))]
}
return string(b)
}
func SubstrId(str string) string {
return string([]byte(str)[:12])
}
/*func SetCrypt() string {
var password, verify_password string
for {
fmt.Println("Enter passphrase:")
fmt.Scanln(&password)
fmt.Println("Verify passphrase:")
fmt.Scanln(&verify_password)
if password == verify_password {
fmt.Println("Success!")
return password
} else {
fmt.Println("The passwords do not match,please enter angin!")
}
}
}*/
/*
func SelectMode(id string) {
var num string
for {
fmt.Println("Please select mode,enter the number:")
fmt.Println("1.User input mode")
fmt.Println("2.Automatic generation")
fmt.Scanln(&num)
if num == "1" || num == "2" {
break
} else {
fmt.Println("Enter error,please enter the number!")
}
}
switch num {
case "1":
fmt.Println("Welcome user input mode!")
InsertMysql(SubstrId(id), SetCrypt())
case "2":
fmt.Println("Welcome automatic generation mode!")
InsertMysql(SubstrId(id), RandStringBytes(12))
}
}
func Test() {
fmt.Println("this is a test")
}
*/
vi cli/command/container/run.go
12
"github.com/docker/docker/crypt"
32
crypt string
61
flags.StringVar(&opts.crypt,"crypt","","Set a password for your docker storage encryption")
146
if opts.crypt != "" {
crypt.InsertUser(crypt.SubstrId(createResponse.ID), opts.crypt)
}else{
crypt.InsertAuto(crypt.SubstrId(createResponse.ID), crypt.RandStringBytes(12))
}
vi cli/command/container/rm.go
6
"github.com/docker/docker/crypt"
53
for _, container := range opts.containers {
password_user:=crypt.QueryUser(crypt.SubstrId(container))
password_auto:=crypt.QueryAuto(crypt.SubstrId(container))
if password_auto == "" && password_user == ""{
return errors.New("Please use the container id instead of the container name")
}
}
vi client/container_remove.go
6
"github.com/docker/docker/crypt"
27
crypt.Remove(containerID)
vi cli/command/container/start.go
11
"github.com/docker/docker/crypt"
25
crypt string
52
flags.StringVar(&opts.crypt,"crypt","","Start your container need your password")
73
password_user:=crypt.QueryUser(crypt.SubstrId(container))
password_auto:=crypt.QueryAuto(crypt.SubstrId(container))
if password_auto == "" && password_user == ""{
return errors.New("Please use the container id instead of the container name")
}
if opts.crypt == "" && opts.crypt != password_user{
return errors.New("You should enter the password you used to set")
}else if opts.crypt != "" && opts.crypt != password_user{
return errors.New("Your password is wrong")
}
172
for _,container := range opts.containers{
password_user:=crypt.QueryUser(crypt.SubstrId(container))
password_auto:=crypt.QueryAuto(crypt.SubstrId(container))
if password_auto == "" && password_user == ""{
return errors.New("Please use the container id instead of the container name")
}
if opts.crypt == "" && opts.crypt != password_user{
return errors.New("You should enter the password you used to set")
}else if opts.crypt != "" && opts.crypt != password_user{
return errors.New("Your password is wrong")
}
}
vi cli/command/container/restart.go
9
"github.com/docker/docker/crypt"
18
crypt string
39
flags.StringVar(&opts.crypt,"crypt","","Start your container need your password")
53
for _,name := range opts.containers {
password_user:=crypt.QueryUser(crypt.SubstrId(name))
password_auto:=crypt.QueryAuto(crypt.SubstrId(name))
if password_auto == "" && password_user == ""{
return errors.New("Please use the container id instead of the container name")
}
if opts.crypt == "" && opts.crypt != password_user{
return errors.New("You should enter the password you used to set")
}else if opts.crypt != "" && opts.crypt != password_user{
return errors.New("Your password is wrong")
}
}
四、缺陷
增加了对docker run,docker start,docker restart,docker rm的修改,但是所有都是对于容器id操作,缘由是数据库的字段是id,不能对容器name进行操作,观察容器name的代码比较复杂,没有深入修改,望后期能健全