Docker入门

安装

1
apt-get install docker.io

安装完成之后,输入以下命令,检查是否安装成功

1
2
root@DIAOAN:/# docker -v
Docker version 20.10.8, build 3967b7d

出现了版本号就说明安装成功了,这时可以运行这条命令,查看Docker是否正常运行

1
2
root@DIAOAN:/# docker run hello-world
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

报错,尝试以下命令启动Docker服务

1
2
3
root@DIAOAN:/# service docker start
root@DIAOAN:/# service docker restart
root@DIAOAN:/# systemctl start docker.service

都不行,查了文档后,才知道如果Docker是运行在WSL上的话,必须要用WSL2才可以,在PowerShell输入以下命令查看WSL的版本

1
2
3
PS C:\WINDOWS\system32> wsl -l -v
NAME STATE VERSION
* Ubuntu-18.04 Running 1

可以看到Ubuntu-18.04的WSL版本为1.使用以下命令升级到WSL2

1
wsl --set-version Ubuntu-18.04 2

再次报错,原因是没有安装Linux内核升级包,下载地址:https://docs.microsoft.com/en-us/windows/wsl/install-win10#step-4---download-the-linux-kernel-update-package

安装完成后,再次运行升级命令,还是报错,是因为电脑没有开启虚拟机平台,这时需要在控制面板中启用虚拟机平台,并且重启进入BIOS,启动虚拟化,重新进入系统后,运行升级命令即可.进入WSL,重启Docker,并检查是否正常运行.

1
2
3
4
5
6
root@DIAOAN:/# service docker restart
* Stopping Docker: docker [ OK ]
* Starting Docker: docker [ OK ]
root@DIAOAN:/# docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.

这样就算安装成功并且正常运行了.


容器使用

查看容器

使用docker ps命令查看容器

1
2
3
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6685130cc957 ubuntu "bash" 6 minutes ago Up 6 minutes determined_hoover

使用docker ps -a查看所有容器,包括已经停止了的

1
2
3
4
5
root@DIAOAN:/# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6685130cc957 ubuntu "bash" 8 minutes ago Up 8 minutes determined_hoover
2e4b99549f80 ubuntu "bash" 9 minutes ago Exited (0) 9 minutes ago affectionate_easley
390684e4cb74 ubuntu "bash" 11 minutes ago Exited (0) 11 minutes ago busy_sutherland

启动容器

启动容器

1
2
3
4
# 启动一个ubuntu容器,但是什么都不做,容器一被创建就被关闭
root@DIAOAN:/# docker run ubuntu
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

启动交互的容器

1
2
3
4
5
6
7
8
9
10
# 启动并进入一个docker容器,但是退出后,容器就被关闭
root@DIAOAN:/# docker run -it ubuntu
root@2e4b99549f80:/# ps
PID TTY TIME CMD
1 pts/0 00:00:00 bash
9 pts/0 00:00:00 ps
root@2e4b99549f80:/# exit
exit
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

参数说明:

  • -i : interactive,交互式操作
  • -t : 分配一个与容器的stdin连接的伪TTY

启动后台容器

1
2
3
4
5
6
# 以后台方式运行容器
root@DIAOAN:/# docker run -itd ubuntu
6685130cc957bf5ecb88d2e0fb8a117fec58a9a5988238dab6649f848bd75262
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6685130cc957 ubuntu "bash" 9 seconds ago Up 8 seconds determined_hoover

参数说明:

  • -d : detach,后台运行容器

启动已停止的容器

使用docker start启动一个停止的容器

1
2
3
4
5
6
# 使用docker start启动一个停止的容器,后面跟停止的容器的ID或名字
root@DIAOAN:/# docker start d5e95c09f750
d5e95c09f750
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d5e95c09f750 ubuntu "bash" 4 minutes ago Up 10 seconds cranky_kalam

停止容器

使用docker stop停止容器

1
2
3
4
5
6
7
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6685130cc957 ubuntu "bash" 12 minutes ago Up 12 minutes determined_hoover
root@DIAOAN:/# docker stop 6685130cc957
6685130cc957
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

重启容器

停止的容器可以通过docker restart重启

1
2
3
4
5
6
7
8
9
10
11
12
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
26bc34f9486d ubuntu "bash" 2 minutes ago Up 2 minutes ubuntu-test
root@DIAOAN:/# docker stop 26bc34f9486d
26bc34f9486d
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@DIAOAN:/# docker restart 26bc34f9486d
26bc34f9486d
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
26bc34f9486d ubuntu "bash" 2 minutes ago Up 2 seconds ubuntu-test

进入容器

在运行容器的时候如果使用了-d参数,容器启动时候会自动进入后台,这时想要进入容器,通过以下指令进入

  • docker attach : 如果从这个容器退出,会导致容器的停止
  • docker exec : 退出容器终端,不会导致容器的停止

使用attach命令

从这个容器退出,会导致容器的停止

1
2
3
4
5
6
7
8
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
26bc34f9486d ubuntu "bash" 5 minutes ago Up 2 minutes ubuntu-test
root@DIAOAN:/# docker attach 26bc34f9486d
root@26bc34f9486d:/# exit
exit
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

使用exec命令

如果从这个容器退出,容器不会停止

1
2
3
4
5
6
7
8
9
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
26bc34f9486d ubuntu "bash" 8 minutes ago Up About a minute ubuntu-test
root@DIAOAN:/# docker exec -it 26bc34f9486d /bin/bash
root@26bc34f9486d:/# exit
exit
root@DIAOAN:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
26bc34f9486d ubuntu "bash" 8 minutes ago Up About a minute ubuntu-test

导出和导入容器

导出容器

要导出本地某个容器,使用docker export

1
2
3
root@DIAOAN:/usr/dockers# docker export 26bc34f9486d > ubuntu.tar
root@DIAOAN:/usr/dockers# ls -a
. .. ubuntu.tar

导入容器

使用docker import导入

1
2
3
4
5
6
7
root@DIAOAN:/usr/dockers# cat ubuntu.tar | docker import - test/ubuntu:v1
sha256:f850ecc2f3ec813024c5d49d643021ac520777c11448e5297de4731085fb3ad2
root@DIAOAN:/usr/dockers# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test/ubuntu v1 f850ecc2f3ec 3 seconds ago 72.8MB
ubuntu latest 1318b700e415 8 days ago 72.8MB
hello-world latest d1165f221234 5 months ago 13.3kB

删除容器

使用docker rm删除容器

1
2
3
4
5
6
7
root@DIAOAN:/usr/dockers# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
26bc34f9486d ubuntu "bash" 31 minutes ago Up 24 minutes ubuntu-test
root@DIAOAN:/usr/dockers# docker rm -f 26bc34f9486d
26bc34f9486d
root@DIAOAN:/usr/dockers# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

可以使用docker container prune删除所有终止的容器

查看日志

使用docker logs查看容器的日志

1
2
3
4
root@DIAOAN:~/dockers# docker logs c617f6fdf5c2
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
172.17.0.1 - - [04/Aug/2021 06:02:04] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [04/Aug/2021 06:02:05] "GET /favicon.ico HTTP/1.1" 404 -

查看进程

使用docker top查看容器运行的进程

1
2
3
root@DIAOAN:/# docker top 34f69064b025
UID PID PPID C STIME TTY TIME CMD
root 1302 1282 0 01:47 pts/0 00:00:00 bash

镜像使用

列出镜像

使用docker images列出本地所有镜像

1
2
3
4
5
root@DIAOAN:/# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
node latest 1d88d89c7230 11 hours ago 907MB
ubuntu latest 1318b700e415 8 days ago 72.8MB
hello-world latest d1165f221234 5 months ago 13.3kB

获取镜像

可以使用docker pull获取新的镜像

1
2
3
4
5
6
7
8
9
10
11
12
root@DIAOAN:/# docker pull ubuntu:13.10
13.10: Pulling from library/ubuntu
Image docker.io/library/ubuntu:13.10 uses outdated schema1 manifest format. Please upgrade to a schema2 image for better future compatibility. More information at https://docs.docker.com/registry/spec/deprecated-schema-v1/
a3ed95caeb02: Pull complete
0d8710fc57fd: Pull complete
5037c5cd623d: Pull complete
83b53423b49f: Pull complete
e9e8bd3b94ab: Pull complete
7db00e6b6e5e: Pull complete
Digest: sha256:403105e61e2d540187da20d837b6a6e92efc3eb4337da9c04c191fb5e28c44dc
Status: Downloaded newer image for ubuntu:13.10
docker.io/library/ubuntu:13.10

删除镜像

使用docker rmi删除镜像

1
2
3
4
5
6
7
8
9
10
root@DIAOAN:/# docker rmi ubuntu:13.10
Untagged: ubuntu:13.10
Untagged: ubuntu@sha256:403105e61e2d540187da20d837b6a6e92efc3eb4337da9c04c191fb5e28c44dc
Deleted: sha256:7f020f7bf34554411031ec0d4f2ab46a2976dad403e1c26bc21dc1bf4c48c8aa
Deleted: sha256:2aac093d13faafda4d0da3534d30274bcc4e5475b1e126c84b9d670862f5e4ef
Deleted: sha256:c676fe3dd3ceb6442e8b23350de88adc6546a52f75bd92dbb1a789b7c6de0fcf
Deleted: sha256:7c6a37fb8fe6a41aaf7c6c7a2cc3d448c01df026b2056a9f35e490e7bf6285cc
Deleted: sha256:b0e8be8278c28daa541ad564fc91dbea99263caa6e5e68db033061c5e08f0315
Deleted: sha256:78dcbd700c6678a7af4422e0ad516628852973a255526f4b617f33db218e1075
Deleted: sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef

构建镜像

可以使用docker build创建一个新的镜像,为此需要创建一个Dockerfile文件

1
2
3
4
5
6
7
8
9
10
11
12
root@DIAOAN:~/dockers# vim Dockerfile
FROM ubuntu
MAINTAINER Fisher "fisher@sudops.com"

RUN /bin/echo 'root:123456' |chpasswd
RUN useradd runoob
RUN /bin/echo 'runoob:123456' |chpasswd
RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
EXPOSE 22
EXPOSE 80
CMD /usr/sbin/sshd -D
root@DIAOAN:~/dockers# docker build -t test .

参数说明:

  • -t : 创建的目标镜像名
  • . : Dockerfile的文件目录

这时可以看到新创建的镜像

1
2
3
root@DIAOAN:~/dockers# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test latest 18a0ee0176cf 2 minutes ago 73.1MB

容器连接

网络端口映射

在运行容器时,使用-p-P来指定容器端口绑定到主机端口

  • -P : 是容器内部端口随机映射到主机的端口。
  • -p : 是容器内部端口绑定到指定的主机端口。
1
2
3
4
5
6
# 将容器的80端口绑定到宿主的10000端口
[root@VM-20-10-centos ~]# docker run -d -p 10000:80 xiaoban
971241ee4519e06ea10d83d145eeb6d18e0dd79d3f4864251a6526a0ccf22151
[root@VM-20-10-centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
971241ee4519 xiaoban "docker-entrypoint.s…" 5 seconds ago Up 5 seconds 0.0.0.0:10000->80/tcp, :::10000->80/tcp silly_keller

Docker容器互联

新建Docker网络

使用docker network新建网络

1
2
3
4
5
6
7
8
root@DIAOAN:~/dockers# docker network create -d bridge test-net
a91712d7878203de0d8f9b98fd1e3fdfc33349113d126406f7f7082f51e8432b
root@DIAOAN:~/dockers# docker network ls
NETWORK ID NAME DRIVER SCOPE
14a9d6753056 bridge bridge local
0e13bb47c88d host host local
2b9de7c88d22 none null local
a91712d78782 test-net bridge local
  • -d:网络类型,有bridge和overlay

新建两个容器并连接到新建的网络

1
2
3
4
5
6
7
8
root@DIAOAN:~/dockers# docker run -itd --name test1 --network test-net ubuntu /bin/bash
73caea235919a692b7a8f5a3b9c59e63ba8cb71c5d8e69c2581f2fe3e243c53e
root@DIAOAN:~/dockers# docker run -itd --name test2 --network test-net ubuntu /bin/bash
5e267e3593199c690dfc7fe76ec3cf241f2d104bc90f1eac3bb8a1f7a7063e7c
root@DIAOAN:~/dockers# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5e267e359319 ubuntu "/bin/bash" 18 seconds ago Up 17 seconds test2
73caea235919 ubuntu "/bin/bash" 23 seconds ago Up 21 seconds test1

进入test1,ping test2

1
2
3
4
5
6
root@DIAOAN:~/dockers# docker exec -it 5e267e359319 /bin/bash
root@5e267e359319:/# ping test2
PING test2 (172.18.0.3) 56(84) bytes of data.
64 bytes from 5e267e359319 (172.18.0.3): icmp_seq=1 ttl=64 time=0.018 ms
64 bytes from 5e267e359319 (172.18.0.3): icmp_seq=2 ttl=64 time=0.040 ms
64 bytes from 5e267e359319 (172.18.0.3): icmp_seq=3 ttl=64 time=0.040 ms

这样,test1容器和test2容器建立了互联关系


Dockerfile

常用指令

FROM

指定定制的镜像基于什么镜像

1
FROM node

COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径

1
COPY ./ /app

WORKDIR

指定工作目录

1
WORKDIR /app

ADD

ADD指令和COPY的使用类似(同样需求下,官方推荐使用COPY).功能也类似,不同之处如下:

  • ADD的优点 : 在执行<源文件>为tar压缩文件的话,压缩格式为gzip,bzip2以及xz的情况下,会自动复制并解压到 <目标路径>.
  • ADD的缺点 : 在不解压的前提下,无法复制 tar 压缩文件.会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢.具体是否使用,可以根据是否需要自动解压来决定.

RUN

用于执行后面跟着的命令行命令,RUN是构建镜像时运行的命令.

1
RUN npm install

CMD

类似于RUN,指令,用于运行程序,但CMD是运行镜像时运行的命令.

1
CMD ["npm","start"]

ENV

设置环境变量,设置的变量在后面的指令中可以使用.

一个示例

1
2
3
4
5
6
# 在Docker中部署一个node项目
FROM node # 基础镜像未node
COPY . /app # 将.目录复制到镜像的/app目录
WORKDIR /app # 定义工作目录为/app
RUN npm install # 构建镜像时安装依赖
CMD ["npm","start"] # 运行镜像时运行项目

Docker Compose

Docker Compose是用于定义和运行多容器 Docker 应用程序的工具.通过编写YAML文件来创建并启动其中的服务.

安装

1
yum install docker-compose

确认安装成功

1
2
[root@VM-20-10-centos composetest]# compose -v
docker-compose version 1.18.0, build 8dd22a9

使用

使用Docker Compose运行服务

  1. 建立一个目录

    1
    2
    mkdir composetest
    cd composetest
  2. 新建app.py文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import time

    import redis
    from flask import Flask

    app = Flask(__name__)
    cache = redis.Redis(host='redis', port=6379)
    # 在这里,redis是redis容器在docker网络上的名字

    def get_hit_count():
    retries = 5
    while True:
    try:
    return cache.incr('hits')
    except redis.exceptions.ConnectionError as exc:
    if retries == 0:
    raise exc
    retries -= 1
    time.sleep(0.5)

    @app.route('/')
    def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)
  3. 新建requirements.txt

    1
    2
    flask
    redis
  4. 新建Dockerfile

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    FROM python:3.7-alpine # 基本镜像是基于alpine的python
    WORKDIR /code # 定义工作目录
    ENV FLASK_APP=app.py # 环境变量
    ENV FLASK_RUN_HOST=0.0.0.0
    RUN apk add --no-cache gcc musl-dev linux-headers # 安装alpine的依赖
    COPY requirements.txt requirements.txt # 复制requirement.txt
    RUN pip install -r requirements.txt # 安装依赖
    EXPOSE 5000 # 定义暴露5000端口
    COPY . . # 复制文件
    CMD ["flask", "run"] # 运行flask
  5. 新建docker-compose.yml

    1
    2
    3
    4
    5
    6
    7
    8
    version: "3.9" # 版本
    services: # 服务
    web: # web服务
    build: . # 通过Dockerfile构建镜像
    ports:
    - "8000:5000" # 绑定端口
    redis: # redis数据库
    image: "redis:alpine" # 通过官方镜像构建
  6. 在刚刚创建的目录里,运行docker-compose up来启动服务

    1
    docker-compose up

    待docker compose构建并启动镜像后,通过curl验证容器是否启动

    1
    2
    3
    4
    5
    6
    [root@VM-20-10-centos ~]# curl localhost:5000
    Hello World! I have been seen 1 times.
    [root@VM-20-10-centos ~]# curl localhost:5000
    Hello World! I have been seen 2 times.
    [root@VM-20-10-centos ~]# curl localhost:5000
    Hello World! I have been seen 3 times.

Docker Compose的网络

使用docker network ls查看docker中的网络

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
[root@VM-20-10-centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
33dbc1e0687d bridge bridge local
89edc5c41440 composetest_default bridge local
# 可以看到这里有一个composetest_default的网络,使用inspect查看它
1ecb9b24cceb host host local
45ccf5177f75 none null local
[root@VM-20-10-centos ~]# docker network inspect composetest_default
[
{
"Name": "composetest_default",
"Id": "89edc5c414409b18d8ba34fa3acf3b3958ec93f1181f45ff4e702802695acfc5",
"Created": "2022-04-17T15:10:31.250424344+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
# 可以看到Containers下有两个对象,就是刚刚yaml文件中的两个服务,两个容器被docker网络连接在一起
"0a763c068bbd5eb4c47b5bd3829d080a3cb1c6ed812a6e7f79ce1dbbc77866d8": {
"Name": "composetest_redis_1",
"EndpointID": "fefec139faf64512c4477d8ced475891d59f39c9f20be6b8bc753b7f38f5e63d",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"0b5453ef504ff560901423ce1036bbc0c61163f7001c009796d50d4019a1ff21": {
"Name": "composetest_web_1",
"EndpointID": "2fa07b4da549dda3a687a05b60f56de7b72f705b1af59d88ab2aeb33ed198967",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "default",
"com.docker.compose.project": "composetest"
}
}
]

停止Compose

在Compose目录下,使用docker compose stopdocker compose down可以停止Compose

1
2
3
[root@VM-20-10-centos composetest]# compose stop
Stopping composetest_web_1 ... done
Stopping composetest_redis_1 ... done