it’s simply a translation to docker tutorial

container和container image

Simply put, a container is a sandboxed process on your machine that is isolated from all other processes on the host machine. That isolation leverages kernel namespaces and cgroups, features that have been in Linux for a long time.

container是一个可以运行的image的实例。可以对一个container进行创建、开始、停止、移动、删除的操作。

container可以在本地机器,虚拟机,或者部署在云上运行。

container与其他的containers是隔离的,运行着自己的软件、二进制文件和配置。

而image包括了container的文件系统,所有的依赖、配置、脚本、二进制文件等等。

需要使用Dockerfile文件构建一个container image。

A Dockerfile is simply a text-based file with no file extension. A Dockerfile contains a script of instructions that Docker uses to create a container image.

docker build指令通过Dockerfile构建了一个全新的container image。

1
2
3
4
5
6
7
# syntax=docker/dockerfile:1
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
EXPOSE 3000

然后运行:docker build -t getting-started .即可成功创建一个image。

首先docker会下载很多layer,因为需要将node:18-alpine镜像下载下来。

使用yarn指令安装应用依赖,CMD指令指定了默认的命令,该命令会在开始一个container时执行。

-t指令指定了image的标签。

命令行中的.指定了需要在当前目录自动查找Dockerfile。

docker run -dp 3000:3000 getting-started

-d表示了新的container将会以detached mode运行(in the background)。-p表示了端口映射,将主机的3000端口与容器的3000端口进行了映射。

除了运行一个container,当然还需要学会移除一个container。

可以使用docker ps指令找到container的状态,使用docker stop指令停止container的运行。用法是docker stop <the-container-id>。当container停止运行后,可以使用指令docker rm <the-container-id>删除相应的container。

Use the docker tag command to give the getting-started image a new name.

这条指令将会创建一个新的image。例子如下:

1
2
3
4
5
6
7
8
9
10
11

⋊> ~/g/app on master ⨯ docker image ls 14:09:03
REPOSITORY TAG IMAGE ID CREATED SIZE
getting-started latest b2956362c236 6 minutes ago 255MB
<none> <none> 977d645603ad 13 minutes ago 255MB
⋊> ~/g/app on master ⨯ docker tag getting-started ccccrrrr/getting-started 14:10:08
⋊> ~/g/app on master ⨯ docker image ls 14:10:36
REPOSITORY TAG IMAGE ID CREATED SIZE
ccccrrrr/getting-started latest b2956362c236 7 minutes ago 255MB
getting-started latest b2956362c236 7 minutes ago 255MB
<none> <none> 977d645603ad 14 minutes ago 255MB

当每一次开启一个container的时候,数据都会被清除。同时,当使用命令remove整个container的时候,数据也会被删除。在特定情况下,持久化数据是较为重要的。

可以在docker desktop中进入指定的容器进行命令行操作,或者是直接使用docker exec,同时制定container id来进行命令行操作。

Volume

Volumes provide the ability to connect specific filesystem paths of the container back to the host machine.

如果一个文件夹背挂在到了一个container中,那么当这个container改变其中的文件时,主机也能够感知到。之后重启,也能得到其中的变化。

1
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started

-v就是指定了将volumn挂载到container的哪个位置。

可以只用docker volume create [volume-name]来创建一个volume。

可以看到创建的volume的具体信息;

1
2
3
4
5
6
7
8
9
10
11
12
docker volume inspect todo-db
[
{
"CreatedAt": "2019-09-26T02:18:36Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
"Name": "todo-db",
"Options": {},
"Scope": "local"
}
]

上面所说都是named volume,即创建一个有名字的volume,然后在创建container时通过名字来使用它们。

同时,还有一种方法,称为bind mounts。这样,可以把源文件挂在到container中,对于修改来说非常方便。

1
2
3
4
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
node:18-alpine \
sh -c "yarn install && yarn run dev"

-w定义了working directory,表明下面的指令应该在哪个目录下运行。

-v定义了讲当前目录挂载到/app上。

node:18-alpine是使用的镜像。

最后一行是要在/app下执行的指令。

指令docker logs -f <container-id>能够看到container运行的全部log。

从上面可以看到,bind mounts更为常见。

Multi container apps

当需要有很多应用一起工作时,最好还是不要让一个container里运行所有的应用。理想情况下应该是一个container运行一个应用。容器之间通过network进行沟通。

有两种方法将一个容器放在指定网络上:1. 在开启他时就指定;2. 连接一个现有的容器。

对于第一种方法:

1
docker run -it --network todo-app nicolaka/netshoot

指定该容器在todo-app的网络下运行。

或者在现有容器中指定运行时的需要通信的端口即可。

Docker Compose

Docker Compose is a tool that was developed to help define and share multi-container applications. With Compose, we can create a YAML file to define the services and with a single command, can spin everything up or tear it all down.

一个docker compose就像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
services:
app:
image: node:18-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos

mysql:
image: mysql:8.0
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos

volumes:
todo-mysql-data:

完成一个docker compose文件后使用命令

1
docker compose up -d

即可创建指定的所有container,让它们一起运行起来。其中-d表示所有container都会在后台运行。

Image building

使用docker image history getting-started能够查看getting-started镜像是如何构建起来的。这个被称为image的layer。增加--no-trunc标志能够看到更完整的输出。

Layer caching

使用history能够看到一个image构建的完整layer,那么当有一层layer改变之后下游的所有layer都会重新构建。

为了能够更好的利用之前构建的layer,可以构建一个逻辑cache,让后续的构建速度更快。d