「Docker」Docker 系列文章1 - 入门

简介

Docker 是一个开源的容器管理平台,它允许开发人员在轻量级容器中运行应用程序。容器是一种轻量级的虚拟化技术,它允许将应用程序及其依赖项打包在一起,并在任何支持容器的环境中运行。这样,开发人员可以确保应用程序在不同的平台上保持一致,并且能够在任何地方快速部署和运行。

Docker可以简单理解为轻量级的虚拟机,但它使用独立于底层操作系统的容器来运行应用程序。与虚拟机相比,Docker 可以更快速地启动和运行应用程序,因为它不需要启动一个完整的操作系统来运行应用程序。这也使得 Docker 更容易在多个环境中进行部署,例如开发环境、测试环境和生产环境。

优点

  • 轻量级:可以通过一行命令完成启动和停止,方便快捷。
  • 可移植:可以将程序及其依赖、运行环境一起打包为一个镜像,可以迁移到任意操作系统,在不同的环境中运行。
  • 隔离:运行时利用沙箱机制形成隔离容器,各个应用互不干扰,可以有效地管理应用程序之间的依赖关系和资源限制。
  • Docker 的生态系统提供了丰富的工具,可以帮助开发人员构建、部署和管理容器化应用程序。

能做什么

  1. 快速部署,解决不同环境中系统差异的问题
    在使用Docker前,我们在不同环境下(如开发环境、测试环境、生产环境等)需要安装、配置、维护不同的应用程序(如JDK、Tomcat、数据库等),不同应用在每个环境都需要做一遍同样的操作,工作量繁重。使用Docker可以自己创建空镜像从头构建(或使用公共仓库中构建好的镜像),直接能够在不同环境中一步到位搭建部署整套应用环境。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现“代码在我机器上没问题啊”的情况。

  2. 解决依赖问题,多个版本软件共存,不污染系统,例如 Python2、Python3,Redis4.0,Redis5.0

    大型项目中依赖关系复杂,依赖的组件非常多,不同组件之间部署时往往会产生依赖兼容性问题。
    例如:一个项目中,部署时需要依赖于node.js、Redis、RabbitMQ、MySQL等,这些服务部署时所需要的函数库、依赖项,甚至Node JS的版本都需要不相同,此时便会出现依赖兼容问题。Docker应用运行在容器中,使用沙箱机制可以将环境互相隔离。不同应用需要不同的版本我们就运行在不同的容器中即可。

  3. 更轻松的扩展和维护
    基于上面的优点,使得Docker在应用复用更为容易,能够使得应用快速扩展,让服务弹性伸缩变得简单,能够轻松地完成动态管理的工作,根据业务需求实时扩展或拆除应用程序和服务。

  4. 快速安装测试/学习软件,用完就可以删除,不把时间浪费在安装软件上。例如 Redis / MongoDB / ElasticSearch / ELK

概念

镜像(Image):像是文件模板,可以理解为软件安装包,可以方便的进行传播和安装。一个镜像可以创建多个容器

容器(Container):是由镜像创建的运行实例,可以理解为软件安装后的状态,每个软件运行环境都是独立的、隔离的,称之为容器。

仓库(Repository):集中存放镜像文件的场所,可以理解为 Maven、Git 的仓库,当我们需要镜像文件的时候,可以从远程仓库中拉取。官方镜像仓库:https://hub.docker.com/

安装

桌面版:https://www.docker.com/products/docker-desktop
服务器版:https://docs.docker.com/engine/install/#server

问题

windows 打开桌面版的时候如果出现了如下问题

Hardware assisted virtualization and data execution protection must be enabled in the BIOS.

则需要开启 WSL2 功能

在控制面板->程序->启用或关闭 windows 功能,勾选Windows虚拟机监控程序平台和适用于Linux的Windows子系统,以开启 Windows 虚拟化和 Linux 子系统(WSL2)

如果出现 WSL 2 installation is incomplete.
The WSL2 Linux kernel is now installed using a separate MSI update package. Please click the link and follow the instructions to install the kernel update: xxx

则需要安装最新版本的 WSL2: https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

配置

镜像加速源

镜像加速器镜像加速器地址
Docker 中国官方镜像https://registry.docker-cn.com
DaoCloud 镜像站http://f1361db2.m.daocloud.io
Azure 中国镜像https://dockerhub.azk8s.cn
科大镜像站https://docker.mirrors.ustc.edu.cn
阿里云https://<your_code>.mirror.aliyuncs.com
七牛云https://reg-mirror.qiniu.com
网易云https://hub-mirror.c.163.com
腾讯云https://mirror.ccs.tencentyun.com

img

安装软件

传统应用安装,可能需要先安装许多的依赖。例如我们安装WordPress (一个基于 PHP 和 MySQL 的免费和开源内容管理系统(CMS))的话,则需要先安装Apache、Php、MySQL等环境后才可以正常安装WordPress。同一系统下也不方便安装多个版本的软件,有些软件还卸载不干净。

相对比之下Dokcer安装更简洁,一个命令就可以快速安装和卸载。也没有系统兼容的问题,Linux专享的软件也可以在Windows下使用。

安装Redis

在Redis官方网站中并没有提供Docker相关的安装方式。

可以通过Docker官方镜像仓库查找Redis镜像:https://hub.docker.com/_/redis

通过命令 docker pull redis 来拉取镜像,也可以通过直接运行 docker run 来创建并运行容器:

1
docker run -d -p 6379:6379 --name redis redis:latest

然后会返回一串容器id(我这里是1c8f24cddd1d7a4accac19e1ef8f7ab68e70f663c3a8f184bbc732fd50f43abd),

就表示创建成功。如果有需要,我们也可以设置更多参数:

1
docker run --restart=always --log-opt max-size=100m --log-opt max-file=2 -p 6379:6379 --name redis -d redis --appendonly yes  --requirepass 123456
  • --restart=always 为开机启动
  • -log 为日志方面的设置
  • -p 为将内部端口映射到外部的端口,将6379端口挂载出去,前面为宿主机端口,后面为镜像内端口
  • -name 为容器名字
  • -d redis 表示后台启动redis
  • -- appendonly yes 开启 redis 持久化
  • -- requirepass 为设置redis访问密码

注意:生产环境尽量不要使用 latest 版本,应使用指定版本号

查看状态

通过以下命令查看容器运行状态:

1
docker ps -a |grep <容器名>

运行 docker ps -a |grep redis 得到以下结果:

1
1c8f24cddd1d  redis  "docker-entrypoint.s…"  47 seconds ago  Up 45 seconds  0.0.0.0:6379->6379/tcp  redis

或者通过容器 id 来查看状态如:docker ps -a | grep 1c8f

查看容器运行日志

1
docker logs --since 30m <容器名/id>
  • –since 30m 是查看此容器30分钟之内的日志情况。

运行docker logs --since 30m redisdocker logs --since 30m 1c8f 得到如下结果:

1
2
3
4
5
6
7
1:C 15 Dec 2022 08:23:37.361 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 15 Dec 2022 08:23:37.361 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 15 Dec 2022 08:23:37.361 # Configuration loaded
1:M 15 Dec 2022 08:23:37.363 * monotonic clock: POSIX clock_gettime
1:M 15 Dec 2022 08:23:37.366 * Running mode=standalone, port=6379.
1:M 15 Dec 2022 08:23:37.366 # Server initialized
1:M 15 Dec 2022 08:23:37.367 * Ready to accept connections

进入容器

1
docker extc -it <容器> <命令>

运行 docker exec -it redis redis-clidocker exec -it 1c8f redis-cli 就可以进入到redis 当中,刚才我们设置了密码,因此要用auth命令登录后才可以使用。

1
2
3
4
5
6
7
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> set abc 1
OK
127.0.0.1:6379> get abc
"1"
127.0.0.1:6379> exit

此时我们已经可以操作并查看到redis中的数据了,证明我们已经安装成功,接下来我们学习怎样停止或删除容器

删除容器

我们需要停止运行中的容器才可以删除

停止命令:

1
docker stop <容器名/id>

运行 docker stop redisdocker stop 1c8f停止容器

删除命令:

1
docker rm <容器名/id>

运行 docker rm redisdocker rm 1c8f 删除容器

通过 docker ps -a 查看 redis 容器已经被删除

删除镜像

查看全部镜像命令:

1
docker images

删除镜像命令:

1
docker rmi <镜像id>

运行 docker rmi 7614 删除镜像, 这里的7614是我的redis的镜像id

常用命令

镜像

获取镜像

docker pull IMAGE_NAME[:Tag] :用于从 Docker 仓库下载镜像,如不显式指定TAG,则默认选择latest标签

查看信息

docker images列出本地主机上已有的镜像信息

docker inspect IMAGE_ID可以获取该镜像的详细信息。

标签镜像

docker tag REPOSITORY:TAG可为本地镜像添加新的标签,例如 docker tag ubuntu:latest latest_ubuntu:latest

搜索镜像

docker search IMAGE_NAME :用于在 Docker 仓库中搜索镜像,例如 docker search mysql

可选参数:

  • --automated=false 仅显示自动创建的镜像
  • --no-trunc=false 输出信息不截断显示
  • -s,–starts=0 指定仅显示评价为指定星级以上的镜像

删除镜像

docker rmi IMAGE[IMAGE...]IMAGE可以为标签或ID。使用镜像ID来删除时,会先尝试删除所有指向该镜像的标签,然后删除该镜像文件本身。

注意:当有该镜像创建的容器存在时,镜像文件默认是无法被删除的。

docker ps -a命令可以看到本机上存在的所有容器。

强制删除镜像用docker rmi -f IMAGE命令。使用-f参数来强制删除一个存在容器依赖的镜像会造成一些遗留问题。正确做法是先删除依赖镜像的所有容器,再来删除镜像。删除容器用docker rm CONTAINER_ID命令。

创建镜像

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG] 基于已有镜像的容器创建

可选参数:

  • -a,–author=“” 作者信息
  • -m,–message"" 提交信息
  • -p,–pause=true 提交时暂停容器运行

举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 14.04 dea1945146b9 6 weeks ago 188MB
[root@localhost test]# docker run -ti ubuntu:14.04 /bin/bash
root@098ab9bc25f8:/# touch test
root@098ab9bc25f8:/# exit
exit
[root@localhost test]# docker commit -m "Added a new file" -a "Docker Test" 098ab9bc25f8 test
sha256:68ceff3107a82641378dee544caeed48e6d544b4d74b525051381b7db7479d35
[root@localhost test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test latest 68ceff3107a8 16 seconds ago 188MB
ubuntu 14.04 dea1945146b9 6 weeks ago 188MB

基于本地模板导入使用cat 镜像压缩包 | docker import -REPOSITORY:TAG命令。

1
2
3
4
5
6
7
8
9
[root@localhost test]# ls
ubuntu-14.04-x86_64-minimal.tar.gz
[root@localhost test]# cat ubuntu-14.04-x86_64-minimal.tar.gz | docker import - ubuntu:14.04-server
sha256:ae63a9e87332075323de0e2cb3e12dd6ea8c6078e006dd937dc0d670c4a8773d
[root@localhost test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 14.04-server ae63a9e87332 12 seconds ago 215MB
test latest 68ceff3107a8 About an hour ago 188MB
ubuntu 14.04 dea1945146b9 6 weeks ago 188MB

存储镜像

docker save -o 压缩包保存名 REPOSITORY:TAG 可存出镜像。

举例如下:

1
2
3
4
5
6
[root@localhost test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 14.04 dea1945146b9 6 weeks ago 188MB
[root@localhost test]# docker save -o ubuntu_server.tar ubuntu:14.04
[root@localhost test]# ls
ubuntu_server.tar

载入镜像

docker load --input 压缩包保存名或者docker load < 压缩包保存名可从导出的文件中重新载入镜像。

举例如下:

1
2
3
4
5
6
7
[root@localhost test]# ls
ubuntu_server.tar
[root@localhost test]# docker load --input ubuntu_server.tar
Loaded image: ubuntu:14.04
[root@localhost test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 14.04 dea1945146b9 6 weeks ago 188MB

构建镜像

docker build:用于从 Dockerfile 创建一个新的镜像

上传镜像

可以使用docker push NAME[:TAG]上传镜像到仓库,默认上传到DockerHub官方仓库。第一次使用必须要先登录。

举例如下:

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
[root@localhost test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 14.04-server ae63a9e87332 4 minutes ago 215MB
test latest 68ceff3107a8 About an hour ago 188MB
ubuntu 14.04 dea1945146b9 6 weeks ago 188MB
[root@localhost test]# docker tag test:latest username/test:latest
[root@localhost test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 14.04-server ae63a9e87332 7 minutes ago 215MB
username/test latest 68ceff3107a8 About an hour ago 188MB
test latest 68ceff3107a8 About an hour ago 188MB
ubuntu 14.04 dea1945146b9 6 weeks ago 188MB
[root@localhost test]# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: username
Password:
Login Succeeded
[root@localhost test]# docker push username/test:latest
The push refers to a repository [docker.io/username/test]
786a798121af: Pushed
7fb9ba64f896: Pushed
4e1e6ac5b9d6: Pushed
48daf661d621: Pushed
bf59e7acf5c4: Pushed
c47d9b229ca4: Pushed
latest: digest: sha256:c46955d49b5b7cf15528b94d5c4fb7028b61c52cf00ee4d14073a92379e2237f size: 1566

容器

创建容器

docker create CONTAINER_NAME 命令来新建一个容器,新建的容器处于停止状态,可以使用docker start <CONTAINER_ID>命令来启动它。

启动容器

启动容器有两种方式:

  • 将在终止状态的容器重新启动,命令为 docker start CONTAINER
  • 基于镜像创建并运行一个新的容器,命令为 docker run CONTAINER , 等价于先执行docker create,再执行docker start

可选参数:

  • -t,让Docker分配一个伪终端并绑定到容器的标准输入上
  • -i,则让容器的标准输入保持打开
  • -d,会让Docker容器在后台以守护形式运行,获取容器输出信息

例如 docker run -t -i ubuntu:14.04 /bin/bash 会启动一个bash终端,允许用户进行交互,举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@localhost test]# docker run -t -i ubuntu:14.04 /bin/bash
root@eac23878c8bf:/# pwd
/
root@eac23878c8bf:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@eac23878c8bf:/# ps
PID TTY TIME CMD
1 pts/0 00:00:00 bash
15 pts/0 00:00:00 ps
root@eac23878c8bf:/# exit
exit
[root@localhost test]# docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello word; sleep 1; done"
2105fbb444b3b028a1b26ec5879d8d282ccc2fa7d0a9776a8a86e808d3414843
[root@localhost test]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2105fbb444b3 ubuntu:14.04 "/bin/sh -c 'while..." 11 seconds ago Up 10 seconds confident_payne
eac23878c8bf ubuntu:14.04 "/bin/bash" 2 minutes ago Exited (0) 2 minutes ago adoring_shockley
[root@localhost test]# docker logs 2105fbb444b3
hello word
hello word
hello word
hello word
...
[root@localhost test]# docker stop 2105

停止容器

docker stop命令用于停止一个正在运行的容器

可选参数:

  • -t, 指定停止容器前等待的秒数。默认值是10秒

扩展:

docker ps -a -q 命令为查看所有(-a)的容器ID(-q),这条命令也可以提供给另外的命令组合使用,如下:

docker stop $(docker ps -a -q) ,命令为停止所有容器

docker restart 将一个运行态的容器终止然后再重新启动它。

进入容器

在运行容器的时候使用-d参数,容器会进入后台,用户无法看到容器中的信息,需要通过命令来进入到容器中进行操作。

docker attach CONTAINER 它允许我们连接到正在运行的容器并在其中运行命令。可以使用它来在容器内部执行操作,例如查看容器的日志或运行容器内的应用程序。这条命令将会打开一个新的终端窗口,可以在容器内部运行命令。要退出容器,可以使用快捷键 Ctrl+PCtrl+Q

注意,docker attach 命令只能用于连接正在运行的容器。如果要连接已停止的容器,我们需要使用 docker exec 命令。

docker exec 命令的语法如下:

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

其中,CONTAINER 是要连接的容器的名称或 ID,COMMAND 是要在容器内部运行的命令,ARG 是命令的参数。

例如,假设想要在名为 my_container 的容器内部运行命令 ls -l,可以使用下面的命令:

1
docker exec my_container ls -l

要在容器中使用 bash,举例如下:

1
2
3
4
5
[root@localhost test]# docker exec -ti a0bb97c292d1 /bin/bash
root@a0bb97c292d1:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@a0bb97c292d1:/# exit
exit

删除容器

可以使用docker rm [OPTIONS] CONTAINER [CONTAINER...]命令删除处于终止状态的容器。

可选参数:

  • -f,–force=false 强行终止并删除一个运行中的容器
  • -l,–link=false 删除容器的连接,但保留容器
  • -v,–volumes=false 删除容器挂载的数据卷

扩展

docker rm $(docker ps -a -q),删除所有容器

导入导出

导出容器是指导出一个已经创建好的容器到一个文件,不管此时这个容器是否处于运行状态,可以使用docker export CONTAINER命令。

1
2
3
4
5
6
7
8
[root@localhost test]# docker run -tid ubuntu:14.04
547e74d47ec3eb30736aee22c1b7bf2acd6e71470a1ade4561007a10b3b14a36
[root@localhost test]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
547e74d47ec3 ubuntu:14.04 "/bin/bash" 6 seconds ago Up 5 seconds unruffled_jennings
[root@localhost test]# docker export 547 > test.tar
[root@localhost test]# ls
test.tar

导出的文件又可以使用docker import命令导入,成为镜像。

1
2
3
4
5
6
7
8
9
10
[root@localhost test]# ls
test.tar
[root@localhost test]# cat test.tar | docker import - test/ubuntu:v1.0
sha256:1ab7c63a882a9bc13ff4673081a237ba8785d47ba69458bfe976c0e5fc7b9c99
[root@localhost test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test/ubuntu v1.0 1ab7c63a882a 22 seconds ago 175MB
ubuntu 14.04-server ae63a9e87332 2 hours ago 215MB
securityweekly/test latest 68ceff3107a8 3 hours ago 188MB
ubuntu 14.04 dea1945146b9 6 weeks ago 188MB

其他命令

  • docker --help 查看帮助命令

  • docker logs:用于查看容器的日志输出。

  • docker volume ls 查看 volume 列表

  • docker network ls 查看网络列表

这只是一些常用的 Docker 命令,Docker 还有很多其他的命令和功能。有关 Docker 命令的完整列表,可以参考 Docker 的官方文档

参考

Docker 快速入门

Docker安装与基本操作