🐳 Docker中Dockerfile和Stack的使用

Docker 是一个开放源代码软件项目,让应用程序布署在软件货柜下的工作可以自动化进行,借此在 Linux 操作系统上,提供一个额外的软件抽象层,以及操作系统层虚拟化的自动管理机制。

这里使用 Docker 将 BlogReaper 和 MySQL 进行容器化

安装和使用

安装过程官方文档说的非常清楚

https://docs.docker.com/install/linux/docker-ce/centos/#install-docker-ce

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
# 清理旧版本
$ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
# 安装必要依赖
$ sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
# 添加安装源
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# 安装最新版本
$ sudo yum install docker-ce
# 查看安装版本
$ yum list docker-ce --showduplicates | sort -r
# 启动
$ sudo systemctl start docker

MYSQL 容器化

首先拉取 MySQL 镜像

1
$ docker pull mysql

需要注意的是这里默认的TAGlatest,而 MySQL 最新的版本为8.0,并不是常用的5.7

使用docker images可以查看已有的镜像

1
2
3
4
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
reaper latest 2d7b67b54617 About an hour ago 23.9MB
mysql latest f991c20cb508 4 weeks ago 486MB

然后启动服务器

1
$  sudo docker run -p 3306:3306 --name mysql_reaper -e MYSQL_ROOT_PASSWORD=password -d mysql

使用 docker ps可以查看正在运行的容器

启动 MySQL 客户端

1
2
3
$ docker run -it --net host mysql "sh"

$ mysql -h127.0.0.1 -P3306 -uroot -ppassword

然后为数据库添加用户和权限

1
2
3
4
5
6
# 新建数据库
CREATE DATABASE reaper;
# 新建用户,可以把host换成%,表示任意IP都可以登陆
CREATE USER 'reaper'@'host' IDENTIFIED BY 'password';
# 授权用户
GRANT all privileges ON reaper TO ‘reaper’@‘host’

PS: 在 8.0 及以上的版本,有些客户端不支持新的默认身份验证插件(caching_sha2_password),我们可以将其换成原来的(mysql_native_password)

1
2
3
4
5
use mysql;
# 查看当前身份验证插件
select user,host,authentication_string from user
# 使用原身份验证插件
alter user 'reaper'@'host' identified with mysql_native_password by 'password';

Dockerfile

使用 Dockerfile,我们可以创建我们专属的 Docker 镜像,这里以一个简单的 Go 应用(BlogReaper)为例子

1
2
3
4
5
6
FROM scratch
COPY config /config
ADD reaper /
ADD https://curl.haxx.se/ca/cacert.pem /etc/ssl/certs/
CMD ["/reaper"]
EXPOSE 30003

FROM

FROM scratch表示从一个空的镜像上创建

如果我们需要专门的编译环境的话,可以使用FROM golang:1.11.3-stretch从镜像库中获取文件

我们可以从https://hub.docker.com/上找到我们需要的镜像,并且基于已经做好的镜像上创建我们的镜像

COPY

COPY 表示复制文件,这里用来复制配置文件到 docker 镜像里面

格式:

  • COPY [--chown=<user>:<group>] <源路径>... <目标路径>
  • COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

ADD

ADD是一种高级的 COPY,不但可以从本地复制文件,而且还可以从互联网上获取文件

对于本次运行的程序,由于存在 https 对外的请求,因此运行的时候遇到了以下的问题

1
x509: failed to load system roots and no roots provided

这是一个非常常见的问题:为了进行 SSL 请求,我们需要 SSL 根证书。

因此需要在 Dockerfile 中加入这一句

1
ADD https://curl.haxx.se/ca/cacert.pem /etc/ssl/certs/

添加根证书到镜像的指定目录中

CMD

一个 Dockerfile 里面只能存在一个 CMD,为镜像创建完成之后执行的命令

EXPOSE

表示需要暴露的端口

使用

静态编译

因为是我们的 main 文件生成的时候依赖的一些库如 libc 还是动态链接的,但是 scratch 镜像完全是空的,什么东西也不包含,所以生成 main 时候要按照下面的方式生成,使生成的 main 静态链接所有的库:

1
$ CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o main .

打包镜像

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
29
30
31
32
33
# 将当前目录的项目打包成docker镜像,并命名为reaper
$ docker build -t reaper .
Sending build context to Docker daemon 24.15MB
Step 1/6 : FROM scratch
--->
Step 2/6 : COPY config /config
---> 61563d9383fe
Step 3/6 : ADD reaper /
---> a8f4c1b1b007
Step 4/6 : ADD https://curl.haxx.se/ca/cacert.pem /etc/ssl/certs/
Downloading [==================================================>] 207.9kB/207.9kB

---> 49cd63c5ed0c
Step 5/6 : CMD ["/reaper"]
---> Running in 871db26955a8
Removing intermediate container 871db26955a8
---> eec5b055118d
Step 6/6 : EXPOSE 30003
---> Running in 27991d0216f3
Removing intermediate container 27991d0216f3
---> 2d7b67b54617
Successfully built 2d7b67b54617
Successfully tagged reaper:latest

# 查看所有镜像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
reaper latest 2d7b67b54617 4 minutes ago 23.9MB
mysql latest f991c20cb508 4 weeks ago 486MB

# 在指定端口后台运行镜像
$ docker run -p 30003:30003 --name blog_reaper -d reaper:latest
7931cba3f241b4c2fc3bd02bce396d5bb7a10abbdca41cf7220411309d233910

通过docker ps可以看到,两个 Docker 进行已经成功运行

1545286380248

Stack

Stack 中包含一系列的 service,这些 service 组成了应用。stack 通过一个 YAML 文件定义每个 service,并描述 service 使用的资源和各种依赖。

有了 Stack,就可以把我们的服务端和数据库打包一起运行咯

定义

首先,定义一个yml文件

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
29
30
31
32
33
34
35
36
37
38
version: '3.1'
services:
db:
image: mysql:latest
command: --default-authentication-plugin=mysql_native_password
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
MYSQL_DATABASE: reaper
MYSQL_USER: reaper
MYSQL_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_root_password
- db_password
ports:
- '3306:3306'

server:
depends_on:
- db
image: reaper:latest
ports:
- '30003:30003'
environment:
MYSQL_DB_HOST: db:3306
MYSQL_DB_USER: reaper
MYSQL_DB_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password

secrets:
db_password:
file: config/db_password.txt
db_root_password:
file: config/db_root_password.txt

volumes: db_data:

首先在开头用version声明版本,这里使用3.1

然后声明服务service

首先是数据库db

使用image表示使用的 docker 镜像为mysql:latest

由于这里使用的是 8.0 的 mysql,因此需要使用command指定默认密码认证组件为mysql_native_password

使用volumes指定挂载的数据库位置。可以将“数据卷”理解为容器中的一个目录,类似于 Linux 中 mount 的概念。创建容器时,可以一并创建数据卷,并且能够挂载一个主机目录为数据卷。

使用docker inspect命令可以查看到,数据库文件挂载在指定的目录上,这样我们每次使用的时候就可以复用之前的数据库

1
2
3
4
5
6
7
8
9
10
11
12
"Mounts": [
{
"Type": "volume",
"Name": "reaperstack_db_data",
"Source": "/var/lib/docker/volumes/reaperstack_db_data/_data",
"Destination": "/var/lib/mysql",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],

然后使用environment指明一些参数,比如数据库密码、用户之类的

用户和密码被存储在docker secrets里面,通过secrets从本地文件中创建,然后运行之后会被映射到/run/secrets下面,使用secrets表示这个容器使用这些秘密文件

最后指明端口

对于服务端,使用depends_on表示所依赖的服务,可以保证数据库运行之后才运行服务器,同样可以通过secrets把密码传递到环境变量中

使用

使用docker stack deploy命令使用预先写好的配置文件

1
2
3
4
5
6
7
$ docker swarm init # 初始化服务
$ docker stack deploy -c docker-compse.yml reaperstack
Creating network reaperstack_default
Creating secret reaperstack_db_password
Creating secret reaperstack_db_root_password
Creating service reaperstack_db
Creating service reaperstack_server

然后查看其运行状态

1
2
3
$ docker stack service ls # 查看服务信息
$ docker stack ps reaperstack # 查看正在运行的容器
$ docker secret ls # 查看加载的密钥

如果不能正常运行可以通过docker logs查看其日志

更新配置之后只需要重新运行一次 docker stack deploy -c docker-compse.yml reaperstack即可

使用rm可以停止当前 stack 并清除

1
$ docker stack rm reaperstack
土豪通道
0%