BG
前几日 Sean 老师发布了一篇文章 – PostgreSQL安装(一): 再简单点儿,用Docker?, 介绍如何快速安装启动 PostgreSQL 数据库。
本文再稍微延伸一点,介绍一下如何自定义 Dockerfile,加入自己想要预制的参数,构建一个自定义的 Docker Image.
Dockerfile 介绍
Dockerfile 是用于定义 Docker 镜像的一种格式。它是一个包含了一系列指令的文本文件,每个指令对应一个镜像层的操作,用于指定如何构建 Docker 镜像。
以下是一个基本的 Dockerfile 示例:
# 使用一个基础镜像
FROM ubuntu:latest# 更新软件包列表
RUN apt-get -y update# 安装软件包
RUN apt-get install -y nginx# 复制文件到容器中
COPY index.html /usr/share/nginx/html/# 设置环境变量
ENV MY_VAR=my_value# 暴露端口
EXPOSE 80# 运行命令
CMD ["nginx", "-g", "daemon off;"]
这个示例 Dockerfile 做了以下几件事:
- 使用最新版的 Ubuntu 作为基础镜像。
- 更新软件包列表,并安装 Nginx。
- 将一个名为 index.html 的文件复制到容器的 /usr/share/nginx/html/ 目录中。
- 设置了一个名为 MY_VAR 的环境变量,其值为 my_value。
- 暴露了容器的 80 端口。
- 在容器启动时,运行 Nginx 并以守护进程模式运行。
使用 Dockerfile,可以通过在 Dockerfile 所在目录执行 docker build
命令来构建 Docker 镜像,例如:
docker build -t my_ngx:latest .
构建结果如下:
从另一个角度讲,如果有一个 Docker Image, 想剖析一下这个镜像如何生成,这样可能做到么?
类似于反编译,这是有难度的,但也可以查看到蛛丝马迹,
比如使用 docker history <image>
命令,查看 Image 的历史。
或者其他第三方工具,比如 dockerfile-from-image。
自定义 PostgreSQL 15 的 Dockerfile
上面介绍过了 Dockerfile 的基本结构,下面就来准备 PostgreSQL 的镜像,基本步骤如下:
1. 基于 CentOS 7 的最新版构建镜像
上面案例中的 FROM ubuntu:latest
改为 FROM centos:7
即可。
这里可以加上镜像的描述,比如维护者:
maintainer="Shawn Yan"
还可以加入其他系统环境变量,比如将语言设定为英文 utf8,
ENV LANG=en_US.UTF-8
2. 替换自带 yum 源,并安装依赖
As you know, CentOS 自带的官方 yum 源连接速度十分、非常、很不理想,所以这里将原有的 repo 文件替换成我常用的 repo。
然后,安装必要的依赖。
由于本文介绍的是构建编译版的 PostgreSQL,所以还需要安装编译工具,以及一些开发包。
这里其实就会出现一个副作用,构建出来的镜像 size 肯定要比直接安装二进制包要大。
# Update yum source
RUN rm -rf /etc/yum.repos.d/*.repo
ADD my.repo /etc/yum.repos.d/my.repo# Install deps
RUN yum -y update \&& yum -y install wget gcc make ...
RUN 命令上面介绍过了,ADD 是将本地文件添加到镜像中的指定位置,这里是将常用的 yum 源写入到 my.repo 再添加到镜像中。
3. 下载 PG 15 源码,并编译
说到编译 PostgreSQL 源码,这里介绍一个参数,--with-extra-version=STRING
, 该参数将STRING附加到PostgreSQL版本号。例如,您可以使用它来标记从未发布的Git快照构建的二进制文件,或者包含带有额外版本字符串的自定义补丁,例如Git描述标识符或分发包发布号。
在 Dockerfile 中,使用 RUN
命令来执行动作,使用 &&
接续动作,使用 \
进行换行。
如此,下载源码,编译,安装一气呵成。
RUN wget https://mirrors.neusoft.edu.cn/postgresql/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.gz \&& echo "$PG_SHA256 postgresql-$PG_VERSION.tar.gz" | sha256sum -c - \&& tar xzf postgresql-$PG_VERSION.tar.gz \&& cd postgresql-$PG_VERSION \&& ./configure --prefix=/opt/postgresql --with-extra-version="-ShawnYan" \&& make -j $(nproc) world \&& make install-world \
4. 创建 postgres 用户,并指定环境变量
在许多 Linux 系统中,PostgreSQL 用户的 UID 默认为 26。这是因为在过去的一些 Linux 系统中,UID 26 被保留给系统用户 postgres,该用户是PostgreSQL 数据库的默认所有者。这意味着如果你使用了默认的 PostgreSQL 安装程序,那么系统会自动为 postgres 用户分配 UID 26。
按照惯例,这里也将 postgres 用户的 UID 设定为 26。并将常用的环境变量预设好,如 PGDATA, PGHOME
RUN useradd -u 26 postgres \&& echo "export PGDATA=/var/lib/pgsql/15/data" >> /home/postgres/.bash_profile \&& echo "export PGHOME=/opt/postgresql" >> /home/postgres/.bash_profile \&& echo "export PATH=\$PGHOME/bin:\$PATH" >> /home/postgres/.bash_profile \
5. 创建 PGDATA 目录,并初始化 PG 实例
创建 PGDATA 路径,并将权限赋予 postgres 用户。然后在 postgres 用户下初始化实例,初始化时指定数据目录。
# PGDATA
RUN mkdir -p /var/lib/pgsql/15/data && chown -R postgres:postgres /var/lib/pgsql
ENV PGDATA=/var/lib/pgsql/15/data# Init
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/postgresql/bin
RUN su -l postgres -c "initdb --pgdata='$PGDATA'" 2>&1 < /dev/null
这样,当运行 docker image 时,镜像里的 PostgreSQL 就已经初始化完成,可以直接使用,而不需要进入容器再次调整。
6. 暴露 5432 端口,准备启动 PostgreSQL 服务
PG 默认使用 5432 端口,如果是实验环境则无需更改。更进一步,这个端口是启动后容器的端口,可通过 <容器IP:5432 > 直接访问容器里的 PG,而非宿主机上的端口,如需绑定到宿主机上的 5432 端口,则需要在启动容器上,传参 -p 5432:5432
。还有一点好处是,可以同时运行若干容器,端口均为 5432,且不会冲突。
# Port
EXPOSE 5432# Start PostgreSQL
CMD ["postgres", "-D", "/var/lib/pgsql/15/data"]
到此,自定义的 PostgreSQL 15 编译版 Dockerfile 已定制完成。
构建 PostgreSQL 15 镜像
Dockerfile 是核心,构建步骤很简单,只需要应用刚才的 dockfile 即可,剩下的交给 Docker。
docker build -f Dockerfile -t my-postgresql:15.2 .
build 时传参 -t
可以将生成的镜像打上标签和版本号。
镜像构建完成后,可使用 docker images
查看镜像。
拉取 PostgreSQL 官方镜像,对比可以发现自定义的镜像文件比官方镜像大 200MB 多。
[root@centos7 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-postgresql 15.2 7028a1396388 14 hours ago 633MB
postgres latest 3b6645d2c145 2 weeks ago 379MB
运行 PostgreSQL 容器
可以指定镜像直接启动容器:
[root@centos7 docker]# docker run -d my-postgresql:15.2
a0ed010c3f0252614f2840dd7485190be6f708066e8822bb10b219e5342474e5
[root@centos7 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a0ed010c3f02 my-postgresql:15.2 "postgres -D /var/li…" 4 seconds ago Up 3 seconds 5432/tcp intelligent_perlman
也可以指定名称启动容器,但要注意 name 需要放到镜像名前:
[root@centos7 docker]# docker run --name pg15 -d my-postgresql:15.2
35d5cdcf4e375d6e1be3bd07730c4774fc58cb3f9586d1c44a4cb81fddcb38d9
[root@centos7 docker]# docker run --name s1 -d my-postgresql:15.2
05ffd0e594d35fc05175e92a1f6919f16fcaa48be6237271e4273ce2097c97a7
[root@centos7 docker]# docker run --name s2 -d my-postgresql:15.2
7ca429feae556ec16bc197f9bac6e0590d28b7b50479f5d1ef88c853689d7858
[root@centos7 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7ca429feae55 my-postgresql:15.2 "postgres -D /var/li…" 3 seconds ago Up 2 seconds 5432/tcp s2
05ffd0e594d3 my-postgresql:15.2 "postgres -D /var/li…" 18 seconds ago Up 16 seconds 5432/tcp s1
35d5cdcf4e37 my-postgresql:15.2 "postgres -D /var/li…" 28 seconds ago Up 27 seconds 5432/tcp pg15
可直接连接容器里的 postgresql:
docker exec -it pg15 psql
也可使用本地 psql 客户端连接容器,但需先确认容器的 IP,或者在启动容器前传参绑定端口:
psql -h 172.17.0.3
后续
定制容器可以做的事情还很多,比如:
- 内置数据库、用户,开箱即用
- 最短时间、最小资源启动主从复制,或配置高可用架构
- 可反复创建、销毁容器,作为实验环境不断练习
– END –
如果这篇文章为你带来了灵感或启发,就请帮忙点『赞』or『在看』or『转发』吧,感谢!(๑˃̵ᴗ˂̵)
本文由mdnice多平台发布