文章目录
一、docker的介绍
1.1 docker是干什么的
当你构建一个软件系统时,通常会涉及到多个组件和依赖,包括操作系统、库文件、配置文件等等。这些组件和依赖可能与你的系统在不同的环境中(例如不同的操作系统、软件版本等等)具有不同的行为,这可能会导致许多问题,例如兼容性问题、环境配置问题等等。
Docker是一个流行的容器化技术,它允许你将软件系统及其所有依赖项打包到一个称为“容器”的独立单元中,以便可以在不同的环境中轻松移植和部署。容器是一个独立的运行时环境,可以与操作系统和硬件隔离,从而可以在任何地方运行。Docker通过简化软件的部署、管理和扩展,使得构建和运行应用程序更加容易。
1.2 为什么docker对资源的消耗远远低于虚拟机
Docker之所以比传统的虚拟机消耗更少的资源,是因为Docker使用的是容器化技术,而不是虚拟化技术。在传统的虚拟机中,每个虚拟机都需要一个完整的操作系统和硬件模拟器,因此每个虚拟机都需要消耗大量的资源。相比之下,Docker容器是在主机操作系统的基础上创建的,因此不需要运行多个操作系统或硬件模拟器。
具体来说,以下是Docker相对于虚拟机能够降低资源消耗的一些原因:
- 轻量级:Docker容器比虚拟机轻量级得多,因为它们共享主机的内核和操作系统,而不是每个容器都运行完整的操作系统。
- 快速启动:Docker容器启动速度很快,通常只需要几秒钟。相比之下,虚拟机需要较长时间才能启动。
- 少量的硬件资源:Docker容器只需要运行所需的程序和依赖项,因此它们不需要像虚拟机那样占用大量的硬件资源。
- 更好的资源利用率:Docker容器可以更好地利用主机的CPU和内存资源,因为它们共享主机的内核和操作系统。
总之,Docker采用的是轻量级的容器化技术,这种技术可以帮助减少资源的消耗,使得应用程序更加轻松地在不同的环境中部署和运行。
1.3 docker层的概念
Docker使用了一种称为Union文件系统的技术,可以将多个文件系统层组合在一起,从而形成一个完整的文件系统。这些文件系统层就是Docker层的概念。
每个Docker镜像都由多个只读文件系统层构成,其中最底层是一个基础镜像(例如Ubuntu、Alpine等),每个上层文件系统层则包含了对底层文件系统层的修改。当你启动一个Docker容器时,Docker引擎会使用这些文件系统层来创建一个新的容器实例,容器中的文件系统就是这些层的组合结果。
以下是Docker层的一些特点和优点:
- 轻量级:由于每个文件系统层都是只读的,因此Docker镜像非常轻量级。当你创建一个新的容器实例时,Docker会创建一个新的读写层,该层是基于之前的只读层进行修改的,因此不会占用额外的磁盘空间。
- 高效性:Docker层使用了Copy-on-Write(COW)技术,这意味着当你在容器中修改文件时,Docker实际上并不会直接修改底层文件系统层,而是会在新的读写层中创建一个新的文件或修改一个现有的文件。这种技术可以帮助提高性能和效率。
- 可维护性: 由于每个文件系统层都是只读的,因此Docker镜像非常易于维护和更新。当你需要更新一个镜像时,你只需要修改相应的文件系统层,而不需要重新构建整个镜像。
上面的内容是我chatgpt回答的,简单来说,docker的每一个层,就像git的一个版本记录,记录的当前层针对之前堆叠层的增删改查操作。并且不同层可以做大量复用,这样就大大降低了磁盘空间的消耗。
二、ubuntu下的docker安装
安装相关的官网
#1 Uninstall old versions
sudo apt-get remove docker docker-engine docker.io containerd runc
#2. Update the apt package index and install packages to allow apt to use a repository over HTTPS:
sudo apt-get update
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
sudo apt-get remove docker docker-engine docker.io containerd runc
#3. Add Docker’s official GPG key:
sudo mkdir -m 0755 -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
#4. Use the following command to set up the repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
#5. Install Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
#6. 开启docker,测试helloworld
sudo service docker start
三、docker-cli基本命令介绍
docker 的命令,可以去官网查看
3.1 docker image系列
Docker镜像是一个只读的模板,它包含了用于创建Docker容器的所有文件和配置信息。镜像可以用于创建多个Docker容器实例,这些实例都是基于同一个镜像创建的,因此它们具有相同的环境和配置。
3.1.1 搜索镜像
可以去docker-hub上搜索自己想要的镜像,以及其对应的tag
以redis为例,官网页面如此
我们尝试一下:
sudo docker pull redis:7-alpine
3.1.2 docker image ls
可以使用ls命令,查看当前有哪些镜像
sudo docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
python latest a41622906035 41 hours ago 925MB
redis 7-alpine aeeb92ae6202 2 weeks ago 29.9MB
nginx latest 3f8a00f137a0 2 weeks ago 142MB
hello-world latest feb5d9fea6a5 17 months ago 13.3kB
我们来解释一下各列的含义
列名 | 释义 |
---|---|
REPOSITORY | 镜像的名字 |
TAG | 镜像的标签,可以简单理解为版本 |
IMAGE ID | 镜像的Id,可以在生成容器时使用id,更精确的创建。也可以在删除时精确匹配 |
CREATED | 创建时间 |
SIZE | 镜像大小 |
3.1.3 docker image rm
删除镜像
sudo docker image rm -f feb5d9fea6a5
3.2 docker container
Docker容器则是基于镜像创建的一个可运行的实例,它是一个隔离的环境,其中包含了应用程序运行所需要的所有文件、配置和依赖项。容器可以被启动、停止、删除、暂停等操作,并且可以与宿主机和其他容器进行通信。
3.2.1 创建容器 docker container create
该命令用于基于镜像创建容器
sudo docker container create -p 3340:80 --name "my-nginx" 3f8a00f137a0
a032812b4f6f69355ec3e7b8cb25b39e9ab32ff567c6351797a20a302b44f6bb
sudo docker container ls --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a032812b4f6f 3f8a00f137a0 "/docker-entrypoint.…" 5 minutes ago Created my-nginx
解释下参数,-p表示端口映射,把镜像的80端口映射到主机的3340端口。–name是起别名。
该套命令还有很多参数,道友们可在官网细细参悟。
3.2.2 查看容器 docker container start
sudo docker container start a032812b4f6f
我们访问localhost:3340 就可以访问nginx了
3.2.3 查看容器 在运行的容器
sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a032812b4f6f 3f8a00f137a0 "/docker-entrypoint.…" 7 hours ago Up 6 hours 0.0.0.0:3340->80/tcp, :::3340->80/tcp my-nginx
如果想停止该容器
sudo docker container stop a032812b4f6f
3.3 容器交互
为方便测试,我们创建一个redis的容器
sudo docker container create -p 6378:6379 --name "my-redis" aeeb92ae6202
sudo docker container ls --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
53e77ee390ae aeeb92ae6202 "docker-entrypoint.s…" 16 seconds ago Created my-redis
a032812b4f6f 3f8a00f137a0 "/docker-entrypoint.…" 9 hours ago Exited (0) 2 hours ago my-nginx
#启动容器
sudo docker container start 53e77ee390ae
#进入容器
sudo docker exec -it 53e77ee390ae sh
我们进入redis后,可以看到redis的容器并没有提供redis的配置,难绷。
3.4 容器卷
3.4.1 容器卷简介
容器卷volumes功能,可以把容器中的文件、文件夹映射到宿主机中。这样做有2个好处:
- 方便修改配置
可以把一些配置文件,资源文件映射到宿主机,这样在宿主机中修改,即可在容器中生效。 - 方便数据持久化
通常,我们会把数据库的存储文件和log文件映射出去,这样在移除容器时,不会导致数据丢失 - 方便迁移
这个很好理解,把配置和数据映射出来,在更换容器时,就很容易迁移了
我们以redis为例,实验下这个功能
3.4.2 配置docker下的redis
#创建映射文件夹
mkdir ~/DOCUMENTS/docker/redis
cd ~/DOCUMENTS/docker/redis
mkdir data
wget https://raw.githubusercontent.com/redis/redis/7.0/redis.conf
注意,wsl中wget https链接可能会被拒绝,可以在windows中下载这个配置
为了测试,我们修改下配置
logfile "/data/redis-log.log" #log文件存放位置
dir "/data/redis" #指定dump.rdb路径
dbfilename dump.rdb
requirepass 密码
3.4.3 容器命令
sudo docker container create \
-p 6378:6379 \
--name "my-redis" \
-v /home/hataksumo/DOCUMENTS/docker/redis/data:/data \
-v /home/hataksumo/DOCUMENTS/docker/redis/config/redis.conf:/etc/redis/redis.conf \
aeeb92ae6202 \
redis-server /etc/redis/redis.conf
1bf50d4b5b06ba3858279436ec1c5d0eba2795157acbe74b0547e9801d6ab4a5
sudo docker container ls --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1bf50d4b5b06 aeeb92ae6202 "docker-entrypoint.s…" 15 seconds ago Created my-redis
a032812b4f6f 3f8a00f137a0 "/docker-entrypoint.…" 19 hours ago Exited (0) 12 hours ago my-nginx
sudo docker container start 1bf50d4b5b06
sudo docker container ls --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1bf50d4b5b06 aeeb92ae6202 "docker-entrypoint.s…" About a minute ago Up 49 seconds 0.0.0.0:6378->6379/tcp, :::6378->6379/tcp my-redis
a032812b4f6f 3f8a00f137a0 "/docker-entrypoint.…" 19 hours ago Exited (0) 12 hours ago my-nginx
sudo netstat -tulpn | grep :6378
tcp 0 0 0.0.0.0:6378 0.0.0.0:* LISTEN 2878/docker-proxy
tcp6 0 0 :::6378 :::* LISTEN 2885/docker-proxy
redis-cli -p 6378
可以看到,连接成功,并且在用户目录也映射出相应的文件
hataksumo@֯��:~/DOCUMENTS/docker/redis/data$ ls
dump.rdb redis.log
注意:这里有一个坑。如果把redis的配置文件的port改为6378,端口映射写成-p 6378:6378时,可能是不生效的。
我们进入redis的docker-file文件可以看到,docker-file命令有一个开放端口的命令,EXPOSE 6379。也可以在docker container create命令中,加入–expose 6378
3.5 网络
对于网络的探究,我们使用nginx为例子。使用最常用的桥接做展示。我们打算配置4个nginx服务器,一个名为gate,另外3个分别为s1,s2,s3。在gate的反向代理中,我们通过配置另外3个nginx的逻辑名来做,而不写具体的ip和端口。这样可以使配置更加通用。
3.5.1 准备配置文件和修改html
首先,我们准备文件夹
建4个文件夹,分别表示gate服务器,和对应的3个微服务
在每个文件夹内,建这几个文件夹
mkdir res res/html config
运行docker容器创建命令,创建4个nginx容器
把nginx中对应的配置文件和默认的html拷到对应的地方
把s1,s2,s3的indix.html的主体改一下
<h1>Welcome to nginx! s{x}-nginx</h1>
<p><em>This is s{x}-nginx</em></p>
把nginx容器的配置拷贝出来
cd ~/DOCUMENTS/docker/nginx/gate/config
sudo docker cp my-nginx:/etc/nginx/conf.d/default.conf default.conf
sudo chmod o+w default.conf
cd ~/DOCUMENTS/docker/nginx/s1/config
sudo docker cp my-nginx:/etc/nginx/conf.d/default.conf default.conf
cd ~/DOCUMENTS/docker/nginx/s2/config
sudo docker cp my-nginx:/etc/nginx/conf.d/default.conf default.conf
cd ~/DOCUMENTS/docker/nginx/s3/config
sudo docker cp my-nginx:/etc/nginx/conf.d/default.conf default.conf
3.5.2 配置gate的config
打开~/DOCUMENTS/docker/nginx/gate/config/default.conf
upstream s_work{
server s1 weight=1;
server s2 weight=1;
server s3 weight=1;
}
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /worker {
proxy_pass http://s_work/;
}
location /worker/s1 {
proxy_pass http://s1/;
}
location /worker/s2 {
proxy_pass http://s2/;
}
location /worker/s3 {
proxy_pass http://s3/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
3.5.3 创建网桥
sudo docker network create --driver bridge nginx
e157926e9c8d764b26128343394af8c998297cec67fb6b52009cc2440a5352d1
3.5.4 创建容器
sudo docker container create \
-p 8000:80 \
--name "gate-nginx" \
-v /home/hataksumo/DOCUMENTS/docker/nginx/gate/res:/usr/share/nginx \
-v /home/hataksumo/DOCUMENTS/docker/nginx/gate/config:/etc/nginx/conf.d \
3f8a00f137a0
c22857441a1a06282412991a16d7df215091a3171b23a844244808ef42afca29
sudo docker container create \
-p 8001:80 \
--name "s1-nginx" \
-v /home/hataksumo/DOCUMENTS/docker/nginx/s1/res:/usr/share/nginx \
-v /home/hataksumo/DOCUMENTS/docker/nginx/s1/config:/etc/nginx/conf.d \
3f8a00f137a0
eff608b0a6057e58af3f447fa0c188310fdc9a76b06228925f54eb2327d17389
sudo docker container create \
-p 8002:80 \
--name "s2-nginx" \
-v /home/hataksumo/DOCUMENTS/docker/nginx/s2/res:/usr/share/nginx \
-v /home/hataksumo/DOCUMENTS/docker/nginx/s2/config:/etc/nginx/conf.d \
3f8a00f137a0
5369f6d5dedc321f94bbf3a981d5e6cc7ea03bd389c2039ae2e62ac8e8654840
sudo docker container create \
-p 8003:80 \
--name "s3-nginx" \
-v /home/hataksumo/DOCUMENTS/docker/nginx/s3/res:/usr/share/nginx \
-v /home/hataksumo/DOCUMENTS/docker/nginx/s3/config:/etc/nginx/conf.d \
3f8a00f137a0
5c12c20296d7d96d1e29fa66d03be02557f807f283c16f45769d04338cb48a3a
3.5.5 把容器加入网络
sudo docker network connect --alias gate nginx gate-nginx
sudo docker network connect --alias s1 nginx s1-nginx
sudo docker network connect --alias s2 nginx s2-nginx
sudo docker network connect --alias s3 nginx s3-nginx
3.5.6 启动各容器与测试
sudo docker container start c22857441a1a eff608b0a605 5369f6d5dedc 5c12c20296d7
在浏览器上访问http://localhost:8000/worker,可以看到负载均衡的效果
3.6 环境变量
有的容器可以通过设置环境变量来做配置,使用-e或–env。这种方式在Java编写的镜像中很常用。在这里暂时不赘述,等遇到后再展示。