Rails on Docker:Docker 入门
💡 Rails on Docker 系列文章是面向 Rails 程序员的 Docker 教程,描述了如何从开发环境到部署环境中应用 Docker。这是系列文章的第一篇。
什么是 Docker
Docker 是一种容器格式。容器是一种虚拟化技术,可以给应用提供一个相互隔离的运行环境。容器有点像虚拟机,但是比虚拟机更轻量,启动时间和占用空间都比虚拟机要小。
图片来源:https://www.docker.com/resources/what-container
相比于虚拟机,容器更好扩容,并且配置方式更标准化。目前云服务商大多提供了容器化部署方式或托管容器集群的服务。
Docker 用于开发环境也能提供不少好处,例如隔离不同应用的系统需求,让开发环境与线上环境等价。在开发时熟悉 Docker 的操作方式,可以减少部署到容器平台时的摩擦。
安装 Docker
Docker 提供了多种操作系统的安装包,可以在 https://www.docker.com/products/docker-desktop 找到适合自己操作系统的安装方式。
安装完毕后,在命令行中执行 docker
命令:
$ docker --version
Docker version 20.10.6, build 370c289
启动一个容器
现在我们来启动一个容器,在命令行输入以下命令:
$ docker run -it ruby:3.0 bash
这个命令会基于 ruby:3.0
镜像启动一个容器,在容器内打开 bash shell。-it
参数表示需要一个可交互的命令行,不然容器在打开 bash shell 之后因为没有输入就会关闭进程。
首次使用 ruby:3.0
镜像需要一些时间下载,启动完成后会看到以下命令提示:
root@970472afca4a:/#
现在终端就已经进入了容器内的 shell,类似于用 ssh 连接到另一台 Linux 主机。容器内的文件、系统应用都是跟宿主机隔离的,我们可以在容器内部安装应用和修改文件而不影响宿主机。
要注意的是目前因为没有设置持久化的方式,在关闭容器后所有更改都会消失。
输入 exit
或者按 ctrl-d
可以退出容器,容器会在发现没有输入后会关闭:
root@970472afca4a:/# exit
exit
挂载 Volume
上面提到,容器跟宿主机环境是隔离的,如果需要在宿主机和容器间共享文件怎么办呢?这时可以通过 Volume 解决。
用以下命令启动一个容器:
$ docker run -it -v $(pwd):/app -w /app ruby:3.0 bash
这里新增了两个参数,我们逐个理解。
-
-v $(pwd):/app
把宿主机当前目录(通过pwd
命令获取)挂载到容器内的/app
目录。 -
-w /app
把工作目录设到/app
,这样一启动容器初始路径就在/app
里。
启动后查看 /app
目录,会显示宿主机当前目录的文件:
root@970472afca4a:/# ls
# ...host files
要注意现在这个目录里的修改都会同步到宿主机上。
小技巧
我经常启动一次性容器做测试,于是在
~/.bash_profile
内设置了以下函数:sandbox() { docker run -it -v $(pwd):/app -w /app $1 bash }
这样我只要输入
sandbox ruby:3.0
就能打开一个已挂载 volume 的临时容器。
用 Dockerfile 定制镜像
前面我们都使用了 ruby:3.0
镜像,这个镜像内只有基础的 Ruby 运行环境,如果需要个别工具,我们在容器内另外安装:
root@2ad3490c73d1:/app# gem install nokogiri
Fetching nokogiri-1.11.7-x86_64-linux.gem
Successfully installed nokogiri-1.11.7-x86_64-linux
1 gem installed
但在退出容器后,容器内的修改都会消失,下次启动的时候又是一个干净的环境。有没有办法保存这些修改呢?其中一个办法是用 docker commit
把运行中的容器保存成镜像,但实际中很少用这个命令,因为有更好的选择——Dockerfile。
Dockerfile 可用于构建 Docker 镜像,现在直接看一个例子。新建一个命名为 Dockerfile
的文件,内容为:
FROM ruby:3.0
RUN gem install nokogiri
WORKDIR /app
然后在同目录下运行命令:
docker build . -t myimage
Docker 就会开始构建镜像,构建完成后,用以下命令查看镜像列表:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myimage latest f248af249511 5 seconds ago 863MB
可以看到,本地镜像中已经多了一个 myimage
镜像。
接着用这个镜像启动一个容器:
$ docker run -it myimage bash
root@879af3165a43:/app# nokogiri -v
# Nokogiri (1.11.7)
# ...
可以看到镜像内已经按照构建配置安装了 nokogiri。
Dockerfile 的命令很多,这里只解释几个常用的:
-
FROM
指定构建的基础镜像。 -
RUN
构建过程执行命令。 -
COPY
从构建目录复制文件到镜像内。 -
WORKDIR
指定工作目录。 -
ENV
设置环境变量。 -
CMD
设置默认的启动命令。
完整的命令列表可以查看 Dockerfile reference,另外关于镜像的优化也需要查看 Best practices for writing Dockerfiles。这里不重复叙述。
总结
这一节介绍了 Docker 是什么,如何用 Docker 启动一次性容器,以及如何用 Dockerfile 构建自己的镜像。
下一节我们将了解如何用 Docker 搭建 Rails 开发环境。