世界上最伟大的投资就是投资自己的教育

首页Docker
随风 · 练气

Docker 入门学习系列文章教程 - docker 部署深入理解 (十)

随风发布于4823 次阅读

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 9acca0e7b7f89acca0e7b7f8some-mysql这个容器的 hash 值。

总结一下,也就是说,如果容器要被外部使用,就要暴露接口,如果容器间使用就可以不必要暴露接口

下一篇文章会写关于在docker-compose中使用--linkdocker network这个关于网络连接的指令。

完结。

下一篇:部署 owncloud 与 phpMyAdmin(十一)

本站文章均为原创内容,如需转载请注明出处,谢谢。

0 条回复
暂无回复~~
相关小书
docker 入门指南

docker 入门指南

零基础学习docker,从应用入手带你深入理解docker

发表于

喜欢
统计信息
    学员: 30007
    视频数量: 1996
    文章数量: 526

© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn

粤公网安备 44152102000088号粤公网安备 44152102000088号 | 粤ICP备19038915号

Top