世界上最伟大的投资就是投资自己的教育
Docker 入门学习系列文章教程 - docker 部署深入理解 (十)
1. 介绍
上一篇:使用 compose 部署 Rocket.Chat 应用 (九)
之所以来介绍关于数据库的部署,是因为数据库很重要,经常会被用到,也是为了下面两篇文章作铺垫。
应该说最主要是为了深入理解 docker 的几个概念,比如匿名卷,数据卷,网络,还有docker-compose
的写法。
学了这些,和理解了这些知识,应该说,以后部署一个别人给你的,或网络上存在的成熟应用,是没有问题的。
2. 端口映射
数据库会以 mysql 作为例子,postgresql 等数据库是一样的。
https://github.com/docker-library/docs/tree/master/mysql
这里有它的使用说明。
可以先看看的。
首先来思考一下,要运行一个 mysql 服务最基本的需求,可能是要先设置一个账号名和密码,不然如何使用呢?
所以:
运行一个最简单的 mysql 镜像,可以这样:
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql
然后用docker ps
查看一下,是这样的:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6679faa19a49 mysql "docker-entrypoint..." 3 seconds ago Up 3 seconds 3306/tcp some-mysql
以mysql
镜像为基础,创建了一个容器,名为some-mysql
,并设置root
密码为my-secret-pw
。
但是这个容器是没有暴露接口的,没有暴露接口的容器也是能登录的,不过需要特殊的手段,没有暴露接口,你就不能用外部的 mysql 等客户端来登录。
如果要暴露接口可以这么做:
docker run --name some-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql
注意,可以使用docker stop some-mysql && docker rm -f $(docker ps -a | grep Exit | awk '{ print $1 }')
来停止使用这个容器
现在使用docker ps
来查看一下。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
feab724df3b6 mysql "docker-entrypoint..." 3 seconds ago Up 2 seconds 0.0.0.0:3306->3306/tcp some-mysql
可见,端口那个部分由3306/tcp
变成了0.0.0.0:3306->3306/tcp
。
0.0.0.0
表示外部的主机能访问到。
3. 环境变量
之前有说过,启动这个 mysql 容器的时候,已经设置了 root 的密码,是通过环境变量的方式设置的,也就是一个参数-e
。
除此之外,你还可以设置其他变量:
- MYSQL_DATABASE 指定使用的数据库,默认会创建
- MYSQL_USER 如果不想使用 root 账号,可以新建一个账号来使用
- MYSQL_PASSWORD 账号的密码
也就是说,mysql 镜像会利用这些传过来的变量,来做一些操作,比如说创建数据库,创建 root 密码等。这样你才能去连接这个 mysql 服务。
4. 匿名卷
我们有一个重要的功能需要注意,就是把数据库的数据保存下来,不会因为 container 停止了,数据就没了。
这个要用到一个叫匿名卷
的问题。
# https://github.com/docker-library/mysql/blob/ee989d0666458d08dd79c55f7abb62be29a9cb3d/5.5/Dockerfile
VOLUME /var/lib/mysql
这个mysql
镜像已经做好了匿名卷,就是/var/lib/mysql
这个目录,意思就是说任何向 /var/lib/mysql
中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。
注意:/var/lib/mysql 是容器中的路径
当然,我们可以使用自己的目录来覆盖这个挂载设置。
使用-v
参数即可:
docker run --name some-mysql -p 3306:3306 -v /home/ubuntu/owncloud/mysql_data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql
当然你可以挂载你任何想持久化的目录和文件。
5. 深入环境变量
开启了 mysql 服务,总要被连接或使用吧。
比如我要进去把数据导出来,可以这么做:
$ docker exec some-mysql sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /some/path/on/your/host/all-databases.sql
$MYSQL_ROOT_PASSWORD
表示引用容器内的变量。
MYSQL_ROOT_PASSWORD
这个变量之前有提过,在 Dockerfile 或一些其他启动脚本就可以先定义好,你再传进去就好了。
整条命令,表示进入容器中执行mysqldump
命令,这个命令使用的 mysql 用户是root
,连接密码,是使用是容器内部的变量MYSQL_ROOT_PASSWORD
。
那如何来证明呢?
可以这么做:
$ docker exec some-mysql sh -c 'echo "$MYSQL_ROOT_PASSWORD"'
my-secret-pw
它会输出你之前启动 mysql 服务器端容器时传过去的密码:my-secret-pw
。
我们再传一个自己的变量,然后重启开启容器:
$ docker run --name some-mysql -p 3306:3306 -v /home/ubuntu/owncloud/mysql_data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -e MYENV=MYVALUE -d mysql
传的变量名是MYENV
,值是MYVALUE
。
结果输出如下:
$ docker exec some-mysql sh -c 'echo "$MYENV"'
MYVALUE
证明我们的猜想是正确的:所以传给容器的变量都被保存着,进入容器都能使用。
除此之外,我们还可以开启一个客户端的容器进程去连接服务器端的容器进程。
$ docker run -it --link some-mysql: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"'
你会发现,开启一个客户端,并且进入其中了。
这部分--link some-mysql:mysql
先不看,我们先来看看后面的环境变量。
怎么又多出了几个变量,不过这些变量都能查看到:
$ docker run -it --link some-mysql:mysql --rm mysql sh -c 'env'
输出如下:
MYSQL_ENV_MYENV=MYVALUE
HOSTNAME=811b319ce670
MYSQL_MAJOR=5.7
SHLVL=0
HOME=/root
MYSQL_ENV_MYSQL_MAJOR=5.7
TERM=xterm
MYSQL_PORT_3306_TCP_ADDR=172.17.0.2
MYSQL_ENV_MYSQL_ROOT_PASSWORD=my-secret-pw
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MYSQL_VERSION=5.7.17-1debian8
MYSQL_ENV_GOSU_VERSION=1.7
MYSQL_PORT_3306_TCP_PORT=3306
MYSQL_PORT_3306_TCP_PROTO=tcp
MYSQL_PORT=tcp://172.17.0.2:3306
MYSQL_PORT_3306_TCP=tcp://172.17.0.2:3306
MYSQL_ENV_MYSQL_VERSION=5.7.17-1debian8
GOSU_VERSION=1.7
PWD=/
MYSQL_NAME=/competent_lamport/mysql
之前使用MYSQL_ROOT_PASSWORD
这种变量好好的,为何又要使用MYSQL_ENV_MYSQL_ROOT_PASSWORD
这个变量呢,原因是因为用了--link
。
把--link
这部分去掉再来试试。
$ docker run -it --rm mysql sh -c 'env'
HOSTNAME=744912e7a7f6
MYSQL_MAJOR=5.7
SHLVL=0
HOME=/root
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MYSQL_VERSION=5.7.17-1debian8
GOSU_VERSION=1.7
PWD=/
看到没?少了好多变量。
想要用什么,拿来用就好了。
其中有一个变量叫MYSQL_PORT_3306_TCP_ADDR
。
这个变量跟 docker 的网络接口有关。
6. link 和网络接口
先来看看--link some-mysql:mysql
这个参数。
以:
分隔分为两部分,第一部分是容器的名称,第二部是网络连接接口的别名。
表示要连接some-mysql
这个容器,这个容器是一个 mysql 服务器程序,并且取了一个别名叫mysql
,这个别名有点类似于localhost
,有点儿像 ip 地址的作用,只是在容器或容器之间用。
这个别名会发挥着很大的作用的,连接这个 mysql 服务器 (some-mysql) 的容器,都可以使用这个别名来找到这台 mysql 服务器的 ip 地址。
下面的章节我们会介绍这个别名的使用。
我们先把这个别名改一下。
$ docker run -it --link some-mysql:db --rm mysql sh -c 'exec env'
HOSTNAME=ab6048fd4ccd
DB_PORT=tcp://172.17.0.2:3306
MYSQL_MAJOR=5.7
SHLVL=0
DB_PORT_3306_TCP=tcp://172.17.0.2:3306
DB_ENV_MYSQL_VERSION=5.7.17-1debian8
HOME=/root
DB_NAME=/clever_goldberg/db
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MYSQL_VERSION=5.7.17-1debian8
DB_ENV_MYSQL_MAJOR=5.7
DB_PORT_3306_TCP_ADDR=172.17.0.2
GOSU_VERSION=1.7
DB_ENV_MYSQL_ROOT_PASSWORD=my-secret-pw
PWD=/
DB_ENV_GOSU_VERSION=1.7
DB_PORT_3306_TCP_PORT=3306
DB_PORT_3306_TCP_PROTO=tcp
看下输出,之前类似以MYSQL
开头的变量MYSQL_PORT_3306_TCP_ADDR
的变量都变成了以DB
开头的变量DB_PORT_3306_TCP_ADDR
。
DB_PORT_3306_TCP_ADDR
是个 ip 地址,它代表的是这台被连接的 mysql 服务器的容器的 ip 地址。
其实用一台命令也可以查出这个 ip 地址。
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name_or_id
container_name_or_id
表示容器的 hash 值,可以写上 mysql 服务器那个容器的名称。
比如:
$ docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' some-mysql
172.17.0.2
果然这个地址一样的。
我们来验证一下。
进入some-mysql
那个容器:
$ docker exec -it some-mysql bash
然后:
$ cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 9acca0e7b7f8
看最后一行172.17.0.2 9acca0e7b7f8
。9acca0e7b7f8
是some-mysql
这个容器的 hash 值。
总结一下,也就是说,如果容器要被外部使用,就要暴露接口,如果容器间使用就可以不必要暴露接口。
下一篇文章会写关于在docker-compose
中使用--link
和docker network
这个关于网络连接的指令。
完结。
本站文章均为原创内容,如需转载请注明出处,谢谢。
© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn
粤公网安备 44152102000088号 | 粤ICP备19038915号
Top