0
点赞
收藏
分享

微信扫一扫

从 0 开始构建一个瀚高数据库 Docker 镜像

本文转自微信公众号“瀚高数据库售前团队”文章
​​​https://mp.weixin.qq.com/s/jFASMI1rJescOQsrOm3kqQ​​

声明

本文章内容仅用于学习、交流,未经瀚高数据库售前团队允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的,利用此文所提供的信息而造成的任何直接或间接的损失,均由使用者本人负责。

简介
TIPS 什么是 Docker

Docker 是一个应用打包、分发、部署的工具。

也可以把它理解为一个轻量的虚拟机,只虚拟软件需要的运行环境,多余的部分都不要;而虚拟机则是一个完整而庞大的系统,其中包含各种是不是必要的软件。

打包:就是把软件运行所需的依赖、第三方库、软件打包到一起,变成一个安装包。
分发:可以把打包好的“安装包”上传到一个镜像仓库,其他人可以非常方便的获取和安装。
部署:拿着“安装包”就能以一个命令运行起来应用,模拟出一模一样的运行环境。

TIPS 容器与虚拟机

传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。

下面的图片比较了 Docker 和传统虚拟化方式的不同之处。
从 0 开始构建一个瀚高数据库 Docker 镜像_docker从 0 开始构建一个瀚高数据库 Docker 镜像_环境变量_02
TIPS Docker 的优势
(1)更高效地利用系统资源。由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高。

(2)更快速的启动时间。Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级启动时间。
(3)一致的运行环境。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现“这段代码在我机器上没问题啊”这类问题。
(4)更轻松的迁移。由于 Docker 确保了执行环境的一致性,使得应用在不同平台间的迁移更加容易。
(5)更轻松的维护和扩展。Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。

TIPS Docker 的三个基本概念

一、Image

Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置件外,还包含了一些为运行时准备的一些配置参数。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

镜像采用特殊的文件系统,设计为分层存储的架构。镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。
从 0 开始构建一个瀚高数据库 Docker 镜像_环境变量_03

采用的文件系统参考:

https://docs.docker.com/storage/storagedriver/

二、Container

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层。

注意:任何保存于容器存储层的信息都会随容器删除而丢失。
从 0 开始构建一个瀚高数据库 Docker 镜像_环境变量_04
三、Registry

Docker Registry 是负责对镜像集中存储、分发镜像的服务,分为公有服务和私有服务,一般使用公有服务 Docker Hub。一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。

TIPS Docker架构

Docker 采用的是 C/S 架构,Docker client 与 Docker daemon 进行交互,Docker daemon 负责构建、运行和分发 Docker 镜像。
从 0 开始构建一个瀚高数据库 Docker 镜像_docker_05
一、Docker Daemon

Docker Daemon(dockerd)不但监听 Docker API 的请求,并且管理着如images、containers、networks 和 volumes 等对象。

二、Docker Client

Docker Client 是用户使用 Docker 的主要方式,可以将用户的命令发送给 dockerd 执行。

更详细内容参考:

https://docs.docker.com/get-started/overview/#docker-architecture

Docker 快速上手

TIPS安装

本文安装以 CentOS 7 虚拟机为例,其他环境请参考官方文档

一、卸载旧版本

如果安装过旧版本的 Dcoker CE,需要先卸载:

sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

二、从仓库安装

官网提供三种安装方式,从 Docker 仓库安装、手动下载 RPM 包安装、采用脚本安装。这里采用从仓库安装的方法。

1.安装 yum-utils 并设置 stable 仓库;

sudo yum install -y yum-utils

sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo

2.安装最新版本 Docker Engine 和 containerd;

sudo yum install docker-ce docker-ce-cli containerd.io

3.启动 Docker;

sudo systemctl start docker

4.通过运行 hello-world 镜像检查是否正确安装。

sudo docker run hello-world
资料参考:

https://docs.docker.com/engine/install/

TIPS 镜像命令

一、查看镜像

[root@192 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 6 months ago 13.3kB

二、拉取镜像

docker pull NAME:TAG

以拉取 postgres 镜像为例(未指定 TAG 默认为 latest );

[root@192 ~]# docker pull postgres
Using default tag: latest
latest: Pulling from library/postgres
a2abf6c4d29d: Pull complete
e1769f49f910: Pull complete
33a59cfee47c: Pull complete
461b2090c345: Pull complete
8ed8ab6290ac: Pull complete
495e42c822a0: Extracting [===> ] 32.77kB/441.7kB
18e858c71c58: Download complete
594792c80d5f: Download complete
794976979956: Downloading [=====================> ] 38.32MB/91.23MB
eb5e1a73c3ca: Download complete
6d6360292cba: Download complete
131e916e1a28: Download complete
757a73507e2e: Download complete

拉取完成后,查看本地已有镜像。

[root@192 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
postgres latest 07e2ee723e2d 3 months ago 374MB
hello-world latest feb5d9fea6a5 6 months ago 13.3kB

三、删除镜像

docker rmi IMAGE

删除所有镜像,即:

docker rmi $(docker images -qa)
Docker 设置国内镜像源可以参考:
http://mirrors.ustc.edu.cn/help/dockerhub.html

TIPS容器命令

一、运行容器

运行容器时,如果本地没有对应的镜像,会先从仓库拉取镜像。

docker run --name pg14 -e POSTGRES_PASSWORD=qwe123 -d postgres

–name 为容器指定一个名字
-e 设定环境变量
-d 指定容器为后台运行

具体使用的参数说明可以使用 docker run --help 查看。

二、查看容器

docker ps -a
[root@192 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
de77f9716542 postgres "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 5432/tcp pg14
ec0accd39909 hello-world "/hello" 36 minutes ago Exited (0) 36 minutes ago friendly_merkle

三、进入容器

[root@192 ~]# docker exec -it pg14 bash
root@de77f9716542:/# psql postgres postgres
psql (14.1 (Debian 14.1-1.pgdg110+1))
Type "help" for help.

postgres=# select version();
version
-----------------------------------------------------------------------------------------------------------------------------
PostgreSQL 14.1 (Debian 14.1-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
(1 row)

postgres=# \q

-it 是以交互式运行容器中的指定应用,上面即运行 bash。

四、启停容器

docker start CONTAINER
docker stop CONTAINER
docker restart CONTAINER

五、查看容器详细信息

docker inspect NAME|ID
[root@192 ~]# docker inspect pg14
[
{
"Id": "84bfdc303cdcd71cf640a13103c0b78576b1c0ddd73316b04ed65b38f9010b70",
"Created": "2022-04-13T14:24:43.815894123Z",
"Path": "docker-entrypoint.sh",
"Args": [
"postgres"
],
"State": {
"Status": "running",
......
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "672e3d3aa95c4eadf2028a33280052f920c7326bb3c36d84faff34eaebaeffdf",
"EndpointID": "5c749f10ab0470d588155c5e8d7f9ea07fe0bccb886f2f515ec894d773822ad4",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]

六、查看日志

[root@192 ~]# docker logs pg14
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".

Data page checksums are disabled.

fixing permissions on existing directory /var/lib/postgresql/data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
......

七、传输文件

# 从主机向容器传文件
docker cp SRC_PATH CONTAINER:DEST_PATH
# 从容器向主机传文件
docker cp CONTAINER:SRC_PATH DEST_PATH

八、删除容器

docker rm CONTAINER

删除所有容器,即:

docker rm $(docker ps -qa)

TIPS 目录挂载
默认情况下,容器的所有数据都被存储在可写层中,这意味着当容器被删除的时候,容器中的数据也就不存在了。

Docker 提供三种数据管理的方式,附图:
从 0 开始构建一个瀚高数据库 Docker 镜像_环境变量_06
如图所示,分别是 volume、bind mount 和 tmpfs mount,其意义有如下几点:

1.volume 存储在主机文件系统中并由 Docker 管理(在Linux路径中为 /var/lib/docker/volumes/)。
2.volume 是 Docker 中持久化数据的最好方式。
3.bind mount 可以存储在主机上的任何地方,甚至是重要的系统文件或目录中。
4.tmpfs mount 仅将数据存储在主机系统内存中,不会写到主机文件系统中。

资料参考:

https://docs.docker.com/storage/volumes/

下面仅介绍使用 -v/–volume 的挂载方式:

1.-v/–volume 由三个参数组成,使用:分隔,且顺序必须正确;
2.对于具名挂载,第一个参数是卷名;对于匿名挂载,第一个参数可以省略;
3.第二个参数是在容器中挂载的路径;
4.第三个参数是可选的,是一个逗号分隔的选项列表。

一、创建并管理卷

# 创建一个名为 mydata 的卷
docker volume create mydata
# 查看已有的卷
docker volume ls
# 查看 mydata 卷的信息
docker volume inspect mydata
# 删除一个卷
docker volume rm mydata
# 删除未被使用的卷
docker volume prune

二、具名挂载

# 直接在挂载时指定卷名:容器内路径
docker run -d --name pg14 -e POSTGRES_PASSWORD=qwe123 -v mydata:/var/lib/postgresql/data postgres
# 或提前创建好卷,然后挂载
docker volume create mydata1
docker run -d --name pg141 -e POSTGRES_PASSWORD=qwe123 -v mydata1:/var/lib/postgresql/data postgres

三、匿名挂载

# 匿名挂载在使用时直接指定容器内路径即可,Docker 会自动创建卷进行管理
docker run -d --name pg142 -e POSTGRES_PASSWORD=qwe123 -v /var/lib/postgresql/data postgres

四、指定路径挂载

# 在创建容器时直接指定挂载在主机上的路径,不会自动创建卷
docker run -d --name pg143 -e POSTGRES_PASSWORD=qwe123 -v /root/my_pgdata:/var/lib/postgresql/data postgres
资料参考:
https://docs.docker.com/storage/

TIPS Dockerfile
Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建,用户可以使用 Dockerfile 快速创建自定义的镜像。

一、FROM 指定基础镜像

定制镜像,即以一个镜像为基础,在其上进行定制。FROM 就是指定基础镜像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令。

二、RUN 执行命令

RUN 指令是用来执行命令行命令的。由于命令行的强大能力,RUN 指令在定制镜像时是最常用的指令之一。

RUN <命令>
RUN ["可执行文件", "参数1", "参数2"]

Dockerfile 中每一个指令都会建立一层,每一个 RUN 的行为,都会新建立一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像,所以不要滥用 RUN 命令。

在执行指令后进行相关的清理工作同样是很重要的一步。前面说过,镜像是多层存储,每一层的东西并不会在下一层被删除,会一直跟随着镜像。因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉。

三、COPY 复制文件

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

COPY 指令将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置。

<源路径>可以是多个。如果源路径为文件夹,复制的时候不是直接复制该文件夹,而是将文件夹中的内容复制到目标路径。

<目标路径>可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。
四、ADD 更高级的复制文件

ADD 指令和 COPY 的格式基本一致。

如果<源路径>为一个 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到<目标路径>去。

在 COPY 和 ADD 指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。

五、CMD 容器启动命令

CMD <命令>
CMD ["可执行文件", "参数1", "参数2"...]

Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。

在运行时可以指定新的命令来替代镜像设置中的这个默认命令。比如:

ubuntu 镜像默认的 CMD 是 /bin/bash,如果我们直接 docker run -it ubuntu 的话,会直接进入 bash。

我们也可以在运行时指定运行别的命令,如 docker run -it ubuntu cat /etc/os-release。这就是用 cat /etc/os-release 命令替换了默认的 /bin/bash 命令了,输出了系统版本信息。

对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出。

六、ENTRYPOINT 入口点

ENTRYPOINT 的格式、目的和 RUN 指令格式一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数–entrypoint 来指定。

CMD 测试:

# 编写 Dockerfile 文件
FROM centos
CMD ["ls", "-a"]

# 构建镜像
docker build -t cmdtest:1.0 .

# run运行,可以看到 ls -a 已经执行
docker run cmdtest:1.0

# 想追加一个命令参数,如果使用下面的写法就会报错
docker run cmdtest:1.0 -l
# 原因是 -l 替换了 CMD 的命令,而 -l 不是命令 ,就报错了

ENTRYPOINT 测试:

# 编写 Dockerfile 文件
FROM centos
ENTRYPOINT ["ls", "-a"]

# 构建镜像
docker build -t entrypointtest:1.0 .

# run 镜像,同样可以看到 ls -a 执行
docker run entrypointtest:1.0

# 这时候加上 -l,就不会报错了
docker run entrypointtest:1.0 -l

七、ENV 设置环境变量

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

这个指令就是设置环境变量而已,无论是后面的其它指令,如 RUN,还是运行时的应用,都可以直接使用这里定义的环境变量。

八、ARG 构建参数

ARG <参数名>[=<默认值>]

构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是,ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。但是不要因此就使用 ARG 保存密码之类的信息,因为 docker history 还是可以看到所有值的。

Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用–build-arg <参数名>=<值>来覆盖。灵活的使用 ARG 指令,能够在不修改 Dockerfile 的情况下,构建出不同的镜像。

九、VOLUME 定义匿名卷

VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中。

在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。

VOLUME /data,这里的 /data 目录就会在容器运行时自动挂载为匿名卷,当然,运行容器时可以覆盖这个挂载设置 -v mydata:/data。

十、EXPOSE 声明端口

EXPOSE <端口1> [<端口2>...]

声明容器运行时提供服务的端口,这只是一个声明,在容器运行时并不会因为这个声明应用就会开启这个端口的服务。

十一、WORKDIR 指定工作目录

WORKDIR <工作目录路径>

使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。如果需要改变以后各层的工作目录的位置,那么应该使用 WORKDIR 指令。

十二、USER 指定当前用户

USER <用户名>[:<用户组>]

USER 改变之后层的执行RUN,CMD 以及 ENTRYPOINT 这类命令的身份。

需要注意的是,USER 只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。

资料参考:

https://docs.docker.com/engine/reference/builder/;https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

TIPS 构建HGDB镜像

下面以构建一个瀚高数据库安全版4.5.7的镜像为例:

1.创建一个 hgdb457 目录,把 rpm 包复制到该目录中。

2.进入到目录中,创建 Dockerfile 文件,并编辑内容;

FROM centos:7

COPY . /root
WORKDIR /root
ENV PGDATA=/opt/HighGo4.5.7-see/data
RUN rpm -ivh hgdb4.5.7-see-centos7-x86-64-20211119.rpm \
&& echo "export LD_LIBRARY_PATH=/usr/lib64:${LD_LIBRARY_PATH}:/opt/HighGo4.5.7-see/lib" >> /opt/HighGo4.5.7-see/etc/highgodb.env \
&& source /opt/HighGo4.5.7-see/etc/highgodb.env \
&& initdb -D ${PGDATA} -A md5 --pwfile=./default_password \
&& chmod 0600 /opt/HighGo4.5.7-see/etc/server.* \
&& cp /opt/HighGo4.5.7-see/etc/server.* ${PGDATA} \
&& echo "listen_addresses = '*'" >> /opt/HighGo4.5.7-see/data/postgresql.auto.conf \
&& sed -i "s/127.0.0.1\/32/0.0.0.0\/0/g" /opt/HighGo4.5.7-see/data/pg_hba.conf \
&& /opt/HighGo4.5.7-see/bin/pg_ctl start -D /opt/HighGo4.5.7-see/data \
&& echo "source /opt/HighGo4.5.7-see/etc/highgodb.env" >> /root/.bashrc \
&& rm hgdb4.5.7-see-centos7-x86-64-20211119.rpm \
&& rm default_password \
&& rm Dockerfile
VOLUME ["${PGDATA}"]
EXPOSE 5866
CMD ["/opt/HighGo4.5.7-see/bin/postgres"]

我们来创建 default_password 密码文件并编辑内容。

Hello@123
Hello@123
Hello@123
###注: 以上密码分别为sysdba、syssao、syssso用户的默认密码###

3.构建镜像

docker build -t hgdb457:1.0 .

执行上述命令后,使用 docker images 即可看到 hgdb457:1.0 的镜像,接下来我们就可以使用这个镜像来生成一个容器。

4.生成容器

docker run --name hgdb457_1 -p 5866:5866 -v hgdb_data:/opt/HighGo4.5.7-see/data --restart=always -d hgdb457:1.0

在这步中,我们使用 hgdb457:1.0 镜像生成了一个名为 hgdb457_1 的容器。

其次,也将容器中的 /opt/HighGo4.5.7-see/data 挂载到了 hgdb_data 卷中,将容器的5866端口映射到主机的5866端口。

5.进入容器

执行 docker exec -it hgdb457_1 bash 即可进入容器,接着执行 psql -U sysdba -d highgo 在输入密码后可登录进数据库。

这里生成的容器就可以满足我们的基本使用需求了。

注意:Docker 中的数据库仅用于测试和学习,不建议用于生产环境。

现在我们有了自己的瀚高数据库镜像,如果想在其他机器的 Docker 中使用该镜像,可以直接使用导出和导入镜像的操作来完成,步骤如下:

1.保存镜像

docker save hgdb457:1.0 -o hgdb457.tar

本步可以将 hgdb457:1.0 镜像导出为 hgdb457.tar 文件。

2.加载镜像

将上一步的 hgdb457.tar 放到新的机器上,导入为镜像:

docker load -i hgdb457.tar

导入镜像完成后,使用 docker images 验证镜像是否正确,然后就可以按照之前的操作生成并使用容器了。

至此,我们已经简单了解了 Docker 并可以构建一个满足基本使用需求的瀚高数据库镜像。如果需要更多的功能,可以根据 Docker 的官方文档和瀚高数据库的使用手册,修改 Dockerfile 并重新构建镜像。

Docker 快速上手版块命令及帮助可参考:
https://docs.docker.com/reference/

本文分享到这里就结束啦感谢您的观看

举报

相关推荐

0 条评论