注:本文大部分命令来自docker.io网站(参考1)。
docker是目前流行的一种容器化技术。容器化技术是一项伟大的发明,它跟传统的虚拟机技术差别很大。这两种技术根据其特点应用在不同的方面;容器一般适用于应用的开发和构建,而虚拟机技术更适合于将底层的设备做强隔离。
一个docker容器本质上就是一个特殊的进程。特殊在于docker控制器为其创建了 NameSpace 隔离运行环境,使用 Cgroups 为其控制了资源开销,包括 docker image(镜像)实现也是利用了 UnionFS 的分层联合技术,这些都是站在 Linux 操作系统的肩膀上实现的。(参考2)
容器的特点包括:
容器运行所需要的文件和环境全部由docker image提供;而docker image的定义文件为Dockerfile。编辑Dockerfile用来设定如何构建docker image:比如定义基础image,定义工作目录,拷贝文件,运行命令,定义启动docker image时的默认命令,等等。
我们将会编辑dockerfile,构建并启动docker image。它将在本地启动一个web服务,页面如下:
首先,从如下地址克隆一份现成的代码作为基础来构建docker image。该代码包括Nodejs后端代码和React框架前端代码。
% git clone https://github.com/docker/getting-started-app.git
进入getting-started-app目录,编辑新文件dockerfile,内容如下:
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
EXPOSE 3000
然后使用如下命令构建docker image。这条命令将在本地创建名为getting-started的镜像。以后将使用镜像的名字getting-started来引用该镜像。
% docker build -t getting-started .
docker image创建成功后,可使用以下命令查看本地镜像。在不指定tag的情况下,tag为默认值latest。
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
getting-started latest b9e0d70526bb 3 hours ago 221MB
最后使用以下命令启动docker container。其中-detach参数指定在后台运行该进程;-publish参数将container内的3000端口映射到本系统的3001端口。这样就可以使用地址http://127.0.0.2:3001访问容器内的服务了。
% docker run --detach --publish 3001:3000 getting-started:latest (--detach --publish可简写为-dp)
f072ae3311e744a904b5dadd6f86c5fe4bc02c0b70d725c537cc82ed8e8bf973
另外,也可以不带-detach参数。这种情况下,docker run命令将占领当前会话;除非手动终止。
% docker run --publish 3001:3000 getting-started:latest (不使用--detach参数)
Using sqlite database at /etc/todos/todo.db
Listening on port 3000^C%
使用docker ps或者docker container ls -a可以查看docker container的状态。
% docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f072ae3311e7 getting-started:latest "docker-entrypoint.s…" 3 minutes ago Up 3 minutes 0.0.0.0:3001->3000/tcp lucid_ritchie
docker exec是非常有用的命令,用来在docker container 内部执行命令。如果使用-it参数,将会创建交互式的输入输出。
% docker exec f072ae3311e7 ls /app
README.md
dockerfile
node_modules
package.json
spec
src
yarn.lock
% docker exec -it f072ae3311e7 /bin/sh
/app # ls /app
README.md dockerfile node_modules package.json spec src yarn.lock
/app # exit
使用docker stop
% docker stop f072ae3311e7
f072ae3311e7
成功停止之后,容器的状态由Up变为Exited。使用docker ps -a命令仍然可以列出它。可以使用docker start
% docker ps -a | grep f072ae3311e7
f072ae3311e7 getting-started ... Exited (0) 5 seconds ago
使用docker rm
% docker rm f072ae3311e7
f072ae3311e7
这时候容器被完全删除,使用docker ps -a命令无法再列出该容器。
我们已经成功构建和启动了docker container,迈出了重要的一步。接下来我们将更多了解如何持久化容器内的数据,多个容器之间如何通讯;目前的容器编排技术;以及由容器技术发展的持续部署等问题。
1.Containerize an application 容器化一个应用
2. 使用 Go 和 Linux Kernel 技术探究容器化原理 - from gopher云原生