Docker初探与安装基于docker的mysql-server服务
由于工作需要,我要在一个docker环境中安装一个mysql,于是对docker和mysql做了一点探究,笔记如下。
零、背景知识
Docker 是一个开源的应用容器引擎,可以 让开发者打包他们的应用以及依赖包到一个可移植的容器中,然后发布 到任何流行的Linux机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
简单来说,Docker将应用程序及其运行环境(包括操作系统、库、配置 等)封装在一个独立的、可移植的“容器”中。这个容器可以在任何支持Docker的平台上运行,无需关心底层的操作系统或硬件差异。这使得开发者可以更加专注于代码开发,而不用担心环境配置的问题,同时也简化 了部署和运维过程。
Docker的核心组件包括镜像(Image)、容器(Container)和仓库(Repository)。镜像是创建容器的基础,它包含了应用程序的所有依赖;容器是从镜像创建的一个运行实例;仓库则是用来存储和分发镜像的地方 。
Docker改变了软件的交付方式,使得开发、测试、部署变得更加高效和 一致。其logo是一条托着一堆集装箱的鲸鱼,更是展示出其包容一切、托付一切的美好愿景。
一、基本概念
在Docker技术中,有一些基本概念需要辨析一下:
- 镜像(Image):Docker镜像是一个只读模板,包含了应用程序 的代码、运行时依赖(比如库、配置文件等),以及运行时的环境。它 是构建容器的基础,类似于软件包(安装包)或安装系统所需的ISO镜像。每个镜像都有一个唯一的ID,并且可以通过命令行工具如
docker pull
从Docker Hub等仓库下载,或者通过docker build
自己创建。 - 仓库(Repository):仓库是存储Docker镜像的地方,可以是私有的(如Docker Hub上的个人账户)或公共的(如Docker Hub、GitHub Container Registry等)。用户可以从仓库下载镜像,也可以将自己的 镜像上传到仓库分享给其他人。
- 容器(Container):容器是镜像的运行实例(Instance)。当你基于一个镜 像启动一个容器时,系统会创建一个新的进程空间,与宿主机隔离,但 共享内核。容器有自己的文件系统、网络设置和端口映射,但不包含宿 主机的文件系统,这使得容器之间互相独立,易于管理和复制(这听起来很像虚拟机,但docker允许容器和宿主机共享内核,不需要对硬件进行模拟,因此其计算开销要远小于虚拟机技术)。docker允许在同一台宿主机上基于同一个镜像启动多个容器,每个容器都是该镜像的一个实例。
关于docker的虚拟化(Virtualization),这里做一点补充。虚拟化是一种技术,允许一台物理计算机同时运行多个独立的操作系统实例;Docker使用的是轻量级虚拟 化,也称为容器虚拟化,它不是在底层创建完整的虚拟机,而是利用操 作系统提供的资源隔离(如命名空间和控制组)来创建容器,从而节省 资源并提高效率。
一句话总结:镜像是docker的基础,仓库是存储docker镜像的地方,容器是镜像的运行实例,而虚拟化是实现容器化的一种技术。
二、安装
这一部分另外参见 Docker的官方文档
docker的运行需要Linux系统内核,因此在Linux系统上的安装很方便,而在macOS和Windows上则需要一些额外的步骤。
(一)在Linux主流发行版上安装docker-engine
参考:
docker-engine是docker中最核心的组件,用于容器的管理与运行。在Linux的几大主流发行版上均可通过下面的方法安装docker-engine,但同样也可以安装docker官方提供的docker-desktop,后者是一个可视化的docker安装和管理工具。
下面我们介绍docker-engine的安装。
在Redhat Enterprise Linux(RHEL)、centOS、Alibaba cloud Linux等红帽系发行版上,使用下面的步骤即可进行安装:
1 | sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo |
上述三条指令分别用于添加docker社区版的软件包仓库、更新软件包列表缓存,以及进行docker安装。dnf是红帽系发行版中较新采用的一个包管理器,如果要使用旧版的yum包管理器,可以使用下面的方法:
1 | sudo yum install -y yum-utils |
在Debian、Ubuntu等deb系发行版上,使用下面的步骤进行安装
1 | # Add Docker's official GPG key: |
(二)macOS安装docker-desktop
首先,从docker官网下载最新版本的docker desktop安装包。随后双击安装包,根据提示完成安装和配置(一般情况下使用默认配置即可),即可完成安装。
(三)windows安装docker-desktop
由于Windows的内核与Linux/Unix那一套相去甚远,按理说Windows原生是不支持docker的。不过好在windows支持hyper-V这种半虚拟化技术(需要硬件支持),且前几年微软推出了一个大杀器——windows subsystem for linux(wsl),使得在Windows上运行Linux程序成为可能,于是docker也就顺理成章能够在Windows上运行了。
因此,要在Windows上安装docker,首先需要开启系统的WSL2功能,或开启hyper-V虚拟化功能。随后,从docker官网下载最新版安装包,并双击安装即可。
三、初识docker
下面以linux系统为例,简单展示一下docker的一些基本操作:
docker images
: 列出本地主机上的所有镜像docker search
: 从Docker Hub中搜索镜像docker pull
: 从Docker Hub下载镜像到本地docker system df
: 显示Docker磁盘使用情况docker rmi
: 删除本地的一个或多个 镜像docker rm
: 删除一个或多个 容器docker commit
: 从正在运行的容器创建一个新的镜像docker build
: 根据Dockerfile构建镜像docker run
: 创建一个新的容器并运行一个命令docker ps
: 列出当前正在运行的容器docker exec -it <container ID/name> bashShell
: 在正在运行的容器中执行命令docker attach <container ID>
: 连接到正在运行中的容器docker start
: 启动一个或多个已经被停止的容器docker stop
: 停止运行中的容器docker restart
: 重启容器
一个简单的示例:
1 | sudo docker search hello-world # 查询名叫hello-world的镜像。这个镜像是docker中很著名的测试镜像 |
运行效果如下:
四、使用docker安装mysql-server
由于我在公共服务器上没有root权限,无法使用正常的方式安装mysql-server,因此只能使用docker曲线救国。下面是探索的结果:
首先,从dockerhub上拉取镜像:
1 | docker search mysql |
终端输出如下:
1 | REPOSITORY TAG IMAGE ID CREATED SIZE |
在拉取完镜像以后,我们基于这个镜像启动一个容器实例。由于mysql-server需要容器和宿主机之间的双向通信,我们的启动脚本会稍微有些复杂,如下(可以写到一个shell脚本里面,然后以脚本的方式运行):
1 |
|
顺便解释一下上面的这些参数:
-p
用于配置网络端口映射,上面的写法是将宿主机的3306端口映射到容器的3306端口。--name
用于指定这个容器的名称。如果不指定,则docker会随机生成一个name(一般是一个形容词+一个名词的格式,其实抛开实用性不谈,docker随机生成的name还挺好玩,例如great_noether
、modest_borg
、frosty_germain
、sleepy_elion
等等)-v
用于将宿主机中的目录(冒号前)挂在到容器中(冒号后)。挂载的目录必须是普通用户有访问权限的目录(最好提前创建,否则后期改权限很麻烦),并且不可以是软链接目录。-e
配置运行时的环境变量,对于mysql-server来说,需要配置的环境变量只有root密码这一个。-u
指定使用特定用户身份登录。默认情况下会以root身份登录,但实际使用时可能会有chown: changing ownership of '/var/lib/mysql/': Operation not permitted
的访问权限问题。因此这里需要指定登录身份。-d
表明让这个docker容器后台运行,就像一个服务程序那样。
运行上面的指令可以让mysql服务在后台运行。可以使用docker ps -a
查看服务状态:
(注意,一些停止运行的容器也会被列出)
要暂停这个容器,可以使用docker stop <container ID/name>
指令。要彻底删除这个容器,可以使用docker rm <container ID/name>
。
我们也可以登录到这个容器内部看一看:
1 | docker exec -it mysql bash |
上面这串指令的意思是在mysql容器中,以交互式的方式(由参数-it
控制)运行bash
指令。效果如下:
五、宿主机mysql客户端连接容器内的mysql服务端
最后,我们看一下如何在宿主机中连接这个数据库。在宿主机中使用下面的命令即可登录(其中,-h
指定mysql-server的IP地址,此处为本地即127.0.0.1(不设置这个参数的话,mysql客户端会去找套接字文件/tmp/mysql.sock
,从而引发一些报错);-P
指定端口,此处为前面使用的3306;-p
指定使用交互式密码输入界面登录数据库)
1 | mysql -h 127.0.0.1 -P 3306 -u root -p |
登陆界面:
1 | (base) cyclin@iZf8z0u1kbopnpeuu32nf5Z:~/miniconda3/pkgs/mysql-connector-python-8.3.0-py310h1b8f574_0$ mysql -h 127.0.0.1 -P 3306 -u root -p |
如果连接失败,可以尝试检查防火墙设置。在ubuntu系统上,防火墙的设置如下
1 | sudo ufw allow 3306/tcp # 允许3306端口的TCP连接 |
关于端口占用情况:前面的启动脚本中 指定了使用宿主机3306端口作为mysql-server的服务端口。然而在公共计算平台上,我们无法保证这一端口没有被其他人使用。因此,在启动docker前,检查端口占用情况也是很重要的。
下面是一些检查端口占用情况的指令:
1 | netstat -tuln # 检查已用端口有哪些 |
运行示例如下:
1 | (base) [zhangwanyu@lih005]~$ netstat -tuln |head |
以上。