赞
踩
通俗地讲,容器是镜像的运行实体。镜像是静态的只读文件,而容器带有运行时需要的可写文件层,并且容器中的进程属于运行状态。即容器运行着真正的应用进程。容器有初建、运行、停止、暂停和删除五种状态。
虽然容器的本质是主机上运行的一个进程,但是容器有自己独立的命名空间隔离和资源限制。也就是说,在容器内部无法看到主机上的进程、环境变量、网络等信息,这是容器与直接运行在主机上进程的本质区别。
容器是基于镜像创建的可运行实例,并且单独存在,一个镜像可以创建出多个容器。运行容器化环境时,实际上是在容器内部创建该文件系统的读写副本。 这将添加一个容器层,该层允许修改镜像的整个副本。
镜像与容器就相当于同样是开发商提供的毛坯房,但是两家人装修出来的完全不一样。
再比如说,我们都学习了 C++ 或者 Java 之类的面向对象的语言,可以理解为镜像为基础类,容器是实例化出来的一个个对象,没有用户需要的不一样,里面的内容也就不一样了。
镜像是静态的文件,并不能提供服务,就好比如我拿了一个 Linux 或者 Windows 的光盘一样,只有安装到主机里面运行起来,才能对外提供服务,我们才能使用。
可以参考:【Docker】Docker 的简介-CSDN博客
这里面的 “为什么要虚拟化、容器化”。
容器的生命周期是容器可能处于的状态。
各生命周期之间的转换关系如图所示:
Docker 在处理 OOM 事件时分为三种情况:
每个容器内部都存在一个 Init 进程,容器中其他所有进程都是此进程的子进程。运行的容器是因为 Init 进程在运行,如果一个子进程因为某种原因造成了退出,那么其父进程也会同步退出,直至 Init 进程也退出。当 Init 进程退出时,也就代表着此容器被关闭。ocker 目前没有办法知道此时的进程退出属于正常退出还是异常退出。当出现容器关闭情况时,Docker Daemon 会尝试再次重新将此容器由 Stopped 状态转为 Running 状态。只有设置了 --restart 参数的容器,Docker Daemon 才会去尝试启动,否则容器会保持停止状态。
Docker “剥夺” 了此容器的 CPU 资源。而其他资源,如 Memory 资源、Network 资源等还保留未动。如此一来,失去了 CPU 资源的进程,是不会被主机内核系统所调度的,所以此容器就处于“冰封”状态。
创建一个新的容器但不启动它。
docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
docker container create
创建一个新的容器并运行一个命令。
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
docker container run
列出容器。
docker ps [OPTIONS]
查看容器日志。
docker logs [OPTIONS] CONTAINER
docker container logs
连接到正在运行中的容器。
docker attach [OPTIONS] CONTAINER
此处按了 Ctrl + C 后会把容器杀死。
此处按了Ctrl + C 不会把容器杀死。
显示报文为:
在容器中执行命令。
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
docker container exec
启动停止的容器。
docker start [OPTIONS] CONTAINER [CONTAINER...]
docker container start
停止运行的容器。
docker stop [OPTIONS] CONTAINER [CONTAINER...]
docker container stop
重启容器。
docker restart [OPTIONS] CONTAINER [CONTAINER...]
强制退出容器。
docker kill [OPTIONS] CONTAINER [CONTAINER...]
注意 :Docker stop 发送的是 SIGTERM 信号, docker kill 发送的是 SIGKILL 信号。
(1)功能
查看容器中运行的进程信息,支持 ps 命令参数。
docker top CONTAINER [ps OPTIONS]
docker container top
注意 :容器运行时不一定有 /bin/bash 终端来交互执行 top 命令,而且容器还不一定有 top 命令,可以使用 docker top 来实现查看 container 中正在运行的进程。
显示容器资源的使用情况,包括: CPU 、内存、网络 I/O 等。
docker stats [OPTIONS] [CONTAINER...]
docker container stats
查看容器详细信息。
docker container inspect [OPTIONS] CONTAINER [CONTAINER...]
注意 :docker inspect 会自动检查是镜像还是容器然后显示相信信息。
用于列出指定的容器的端口映射,或者查找将 PRIVATE_PORT NAT 到面向公众的端口。
docker port CONTAINER [PRIVATE_PORT[/PROTO]]
docker container port
在容器和宿主机之间拷贝文件。
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
docker container cp
检查容器里文件结构的更改。
docker diff CONTAINER
从容器创建一个新的镜像。
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
暂停容器中所有的进程。
docker pause CONTAINER [CONTAINER...]
恢复容器中所有的进程。
docker unpause CONTAINER [CONTAINER...]
docker container unpause
删除停止的容器。
docker rm [OPTIONS] CONTAINER [CONTAINER...]
docker rm $(docker ps -a -q)
导出容器内容为 tar 文件
docker export [OPTIONS] CONTAINER
docker container export
阻塞运行直到容器停止,然后打印出它的退出代码。
docker wait CONTAINER [CONTAINER...]
重命名容器。
docker rename CONTAINER NEW_NAME
删除所有停止的容器。
docker container prune [OPTIONS]
更新容器配置。
docker update [OPTIONS] CONTAINER [CONTAINER...]
docker container update
可以看到容器的启动时间变短:
docker container rm 43 49 50 ...
docker container rm $(docker container ls -aq)
docker container ls -a
docker container rm $(docker container ls -q --filter status=exited)
docker container ls -a
注意 :其他命令在做批量处理的时候同样可以类比, 比如批量停止: docker container stop $( docker container ps -aq )
-p 8106:80 表示端口映射,第一个端口表示映射到宿主机的端口,第二个端口表示映射到 Docker 容器的端口。
下面实践一下 attached 模式的用法:
可以看到 nginx 主页已经展现在浏览器上,当我们刷新访问后发现在标准输出上会打印一些相关的 log 出来。
执行命令查看当前容器状态,可以发现该容器已经退出:
在 docker container run -p 80:80 nginx 命令基础上加一个-d 或者 --detach 选项表示 detached 模式,即在后台执行。
下面来实践一下 detached 模式的用法:
刷新浏览器可以看到此时在后台已经打印出来相关的日志:
当创建好一个容器之后,可能需要去容器内部获取一些信息或执行一些命令,就需要进入到交互式模式。例如创建一个 Ubuntu 容器之后,需要到系统里输入各种 Shell 命令和系统进行交互就需要进入交互式模式才可以完成。
进入到容器的交互 shell 中,可以在该 shell 下执行对应的命令:
此时就可以正常访问了:
输入 Ctrl + C 并不会产生什么影响,在交互式 shell 中输入 exit 则退出:
发现容器自动删除了:
容器重启选项如下:
如果容器启动时没有设置–restart 参数,则通过下面命令进行更新:
配置环境变量:
可以查看一个容器的详细信息,比如我们可以查看所有设置的环境变量。
可以直接借助 docker 的容器环境执行一些命令,比如容器中有某个命令而宿主机上没有这个时候借助容器可以完成某些任务。
如果使用 import 导入 save 产生的文件,虽然导入不提示错误,但是启动容器时会提示失败,会出现类似 "docker: Error response from daemon: Container command not found or does not exist" 的错误。我们必须指定启动命令,因为 export 丢失了元数据信息。
刷新访问几次页面:
添加 aux,可以看到占用的内存和 CPU 信息:
官方网站:mysql - Official Image | Docker Hub
查看官网的启动用例:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d
mysql:tag 指定了 mysql 的密码信息
启动一个 mysql,并指定密码和端口开放:
可以看到已经可以正常登录 mysql 了:
以 mysql workbench 为例:
在 Web 应用发展的初期,那时关系型数据库受到了较为广泛的关注和应用,原因是因为那时候 Web 站点基本上访问和并发不高、交互也较少。后来随着访问量的提升,使用关系型数据库的 Web 站点多多少少都开始在性能上出现了一些瓶颈,而瓶颈的源头一般是在磁盘的 I/O 上。而随着互联网技术的进一步发展,各种类型的应用层出不穷,这导致在当今云计算、大数据盛行的时代,对性能有了更多的需求,主要体现在以下几个方面:
为了克服这一问题,NoSQL 应运而生,它同时具备了高性能、可扩展性强、高可用等优点,受到广泛开发人员和仓库管理人员的青睐。
Redis 全称 Remote Dictionary Server,中文名为远程字典服务器。Redis 是现在最受欢迎的 NoSQL 数据库之一,Redis 是一个使用 ANSI C 编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,其具备如下特性:
开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。
几乎所有的大厂都在使用 Redis。Redis 提供了多种数据类型,String 类型、哈希类型、列表类型、集合类型和顺序集合类型,借助这些类型可以方便的实现多种应用,如缓存系统(“热点” 数据:高频读、低频写)、计数器、消息队列系统、实时排行榜、社交网络。
Redis 就像一个新华字典,可以根据某个字符可以很快的找到字典对应的字。
官方网站:redis - Official Image | Docker Hub
可视化工具下载地址:AnotherRedisDesktopManager 发行版 - Gitee.com
双击下载好的 .exe 文件:
选择为所有用户安装:
修改安装目录:
源就是来源。就是你安装软件时,程序从哪里获取软件包(安装程序在你的机器上,但需要安装的东西却在软件源服务器上)。
源在 Ubuntu 下,它相当于软件库,需要什么软件,只要记得正确的软件名就可以用命令抄安装:其实你可以把他称为软件仓库。安装软件时,就是从仓库里面调取数据放在你的机器上。
sudo apt-get install 软件名
例如:要安装 gcc 软件,那么就可以再终端中输入 sudo apt-get install gcc,这样就能帮我们装好 gcc 软件,如果源里没有这个软件时,此命令就没法完成。
镜像(Mirroring)是一种文件存储形式,是冗余的一种类型,一个磁盘上的数据在另一个磁盘上存在一个完全相同的副本即为镜像。
常见的镜像文件格式有 ISO、BIN、IMG、TAO、DAO、CIF、FCD。
所谓镜像文件其实和 ZIP 压缩包类似,它将特定的一系列文件按照一定的格式制作成单一的文件,以方便用户下载和使用,例如一个测试版的操作系统、游戏等。(安装过操作系统的人应该对 xxx.iso 不陌生)
镜像文件不仅具有 ZIP 压缩包的“合成”功能,它最重要的特点是可以被特定的软件识别并可直接刻录到光盘上。
镜像源就是把官方的源做一个镜像,可以在这下载软件。比如:ubuntu 官方源在国外,下载软件可能会很慢,这时候就需要换成国内的镜像源。
基于 ubuntu 来制作 C++容器,运行输出 "HelloWorld"。
可以把镜像源当做一个代理商,比如买车本来要去车厂,但是设置了一个个 4S 店以后,直接去 4S 店就好了,不用跑到车厂。
CentOS Vault - USTC Mirror Help
使用 Spring Boot 创建一个简单的 demo, 在浏览器输出:"hello docker!"。
选择 Spring Boot 2.x 的第一个发布版本 2.0.2.RELEASE,如下在 pom.xml 中添加 spring-boot 依赖
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
- http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <groupId>org.example</groupId>
- <artifactId>springboot-demo</artifactId>
- <version>1.0-SNAPSHOT</version>
-
- <properties>
- <maven.compiler.source>8</maven.compiler.source>
- <maven.compiler.target>8</maven.compiler.target>
- </properties>
-
- <!-- 项目的 pom 定义继承自 SpringBoot 的父 pom -->
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.0.2.RELEASE</version>
- </parent>
-
- <!-- Web 项目,添加spring-boot-starter-web依赖即可,版本号由父pom已经定义好了,此处省略 -->
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- </dependencies>
-
- <!-- 添加 spring boot 项目构建插件 -->
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>repackage</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </project>
- package com.bittech.boot;
- import org.springframework.boot.SpringApplication;
- import
- org.springframework.boot.autoconfigure.SpringBootApplication;
-
- @SpringBootApplication
- public class ExampleApplication {
- public static void main(String[] args) {
- SpringApplication.run(ExampleApplication.class, args);
- }
- }
- package com.bittech.boot;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- @RestController
- @RequestMapping(value = "/hello")
- public class ExampleController {
-
- @RequestMapping(value = "")
- public String index() {
- return "Hello Spring Boot for Docker World!";
- }
- }
生成的 jar 包位于项目根路径下的 target 目录:
- # 在 cmd 中执行命令测试 jar 包是否可用
- java -jar D:\code\java_relearn\springboot-demo\target\springboot-demo-1.0-SNAPSHOT.jar
启动容器后,访问 localhost:8080/hello 查看运行结果,确认 jar 包可用:
- [root@VM-8-5-centos spring_demo]$ pwd
- /home/zsc/dockerfile/spring_demo
- [root@VM-8-5-centos spring_demo]$ ls
- Dockerfile springboot-demo-1.0-SNAPSHOT.jar
- root@139-159-150-152:/data/myworkdir/container# docker pull
- ubuntu:22.04
- 22.04: Pulling from library/ubuntu
- 2ab09b027e7f: Pull complete
- Digest:
- sha256:67211c14fa74f070d27cc59d69a7fa9aeff8e28ea118ef3babc295a0428
- a6d21
- Status: Downloaded newer image for ubuntu:22.04
- docker.io/library/ubuntu:22.04
- root@139-159-150-152:/data/myworkdir/container# docker run -p
- 8080:8080 --name myjava -it ubuntu:22.04 bash
- root@50d527b8343e:/#
- root@50d527b8343e:/# sed -i
- 's@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g'
- /etc/apt/sources.list
- root@50d527b8343e:/#
- apt update
- apt install -y openjdk-8-jdk
docker cp ./springboot-demo-1.0-SNAPSHOT.jar myjava:/app.jar
- root@071ceaad511a:/# ll
- total 15824
- drwxr-xr-x 1 root root 4096 Mar 24 10:28 ./
- drwxr-xr-x 1 root root 4096 Mar 24 10:28 ../
- -rwxr-xr-x 1 root root 0 Mar 24 10:24 .dockerenv*
- -rw-r--r-- 1 root root 16125993 Mar 24 10:23 app.jar
- lrwxrwxrwx 1 root root 7 Mar 8 02:05 bin -> usr/bin/
- drwxr-xr-x 2 root root 4096 Apr 18 2022 boot/
- drwxr-xr-x 5 root root 360 Mar 24 10:24 dev/
- drwxr-xr-x 1 root root 4096 Mar 24 10:27 etc/
- drwxr-xr-x 2 root root 4096 Apr 18 2022 home/
- lrwxrwxrwx 1 root root 7 Mar 8 02:05 lib -> usr/lib/
- lrwxrwxrwx 1 root root 9 Mar 8 02:05 lib32 -> usr/lib32/
- lrwxrwxrwx 1 root root 9 Mar 8 02:05 lib64 -> usr/lib64/
- lrwxrwxrwx 1 root root 10 Mar 8 02:05 libx32 -> usr/libx32/
- drwxr-xr-x 2 root root 4096 Mar 8 02:05 media/
- drwxr-xr-x 2 root root 4096 Mar 8 02:05 mnt/
- drwxr-xr-x 2 root root 4096 Mar 8 02:05 opt/
- dr-xr-xr-x 206 root root 0 Mar 24 10:24 proc/
- drwx------ 2 root root 4096 Mar 8 02:08 root/
- drwxr-xr-x 1 root root 4096 Mar 24 10:27 run/
- lrwxrwxrwx 1 root root 8 Mar 8 02:05 sbin -> usr/sbin/
- drwxr-xr-x 2 root root 4096 Mar 8 02:05 srv/
- dr-xr-xr-x 13 root root 0 Mar 24 10:24 sys/
- drwxrwxrwt 1 root root 4096 Mar 24 10:27 tmp/
- drwxr-xr-x 1 root root 4096 Mar 8 02:05 usr/
- drwxr-xr-x 1 root root 4096 Mar 8 02:08 var/
java -jar ./app.jar
通过 docker stats,可以看到内存已经被限制到 300m 了:
- for i in `seq 1 $(cat /proc/cpuinfo |grep "physical id" |wc -l)`
- do
- dd if=/dev/zero of=/dev/null &
- done
-
- # cat /proc/cpuinfo |grep “physical id” | wc -l 可以获得CPU的个数,将其表示为 N
- # seq 1 N 用来生成1~N之间的数字
- # for i in seq 1 N; 就是从1~N循环执行命令
- # dd if=/dev/zero of=/dev/null 执行dd命令,输出到/dev/null,实际上只占用CPU,没有IO操作
- # 由于连续执行N个(N是CPU个数)的dd命令,且使用率为100%,这时调度器会调度每个dd命令在不同的CPU上处理,最终就实现所有CPU占用率100%
docker create 命令从 Docker 映像创建一个全新的容器。但是,它不会立即运行它。
docker start 命令将启动任何已停止的容器。如果使用 docker create 命令创建容器,则可以使用此命令启动它。
docker run 命令是创建和启动的组合,因为它创建了一个新容器并立即启动它。实际上,如果 docker run 命令在您的系统上找不到上述映像,它可以从 Docker Hub 中提取映像。
要了解 docker load 与 docker import 命令的区别,还必须知道 docker save 与 docker export 命令。
- docker save images_name:将一个镜像导出为文件,再使用 docker load 命令将文件导入为一个镜像,会保存该镜像的的所有历史记录。比 docker export 命令导出的文件大,很好理解,因为会保存镜像的所有历史记录。
- docker export container_id:将一个容器导出为文件,再使用 docker import 命令将容器导入成为一个新的镜像,但是相比 docker save 命令,容器文件会丢失所有元数据和历史记录,仅保存容器当时的状态,相当于虚拟机快照。
既可以使用 docker load 命令来导入镜像库存储文件到本地镜像库,也可以使用 docker import 命令来导入一个容器快照到本地镜像库。二者的区别在于容器快照将会丢弃所有的历史记录和元数据信息,而镜像存储文件将保存完整记录,体积也会更大。
- docker rm:删除一个或多个容器。
- docker rmi:删除一个或多个镜像。
- docker prune:用来删除不再使用的 docker 对象。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。