docker is developed based on Go language! Open source project!
docker official website: https://www.docker.com/
Documentation: https://docs.docker.com/ Docker’s documentation is super detailed!
Warehouse: https://hub.docker.com/
1. The role of docker
1.1. Analysis of previous virtual machine technology
app: some of our apps
lib: libraries required for operation
kernel: kernel
One overall environment contains many applications
Disadvantages of virtual machine technology :
1. It takes up a lot of resources
2. Many redundant steps
3. Startup is very slow!
1.2. Analysis of containerization technology
- Containerization technology is not about simulating a complete operating system
-
Isolation mechanism: Each container is isolated from each other, lib and app are independent, and server resources are fully utilized. Also, if a single lib crashes, it will not cause problems in other apps.
-
Compare the differences between Docker and virtual machine technologies:
-
A traditional virtual machine virtualizes a piece of hardware, runs a complete operating system, and then installs and runs software on this system.
-
The applications in the container run directly on the host. The container does not have its own kernel, nor does it virtualize our hardware, so it is lightweight.
-
Each container is isolated from each other. Each container has its own file system and does not affect each other.
-
1.3. Introduction to DevOps
DevOps, which refers to development and operation and maintenance, has four important characteristics:
-
Faster application delivery and deployment
- Traditional: a bunch of help documentation, installer.
- Docker: Package the image for release testing and run it with one click. (so cool)
-
More convenient upgrades and expansion and contraction
- After using Docker, deploying applications is just like building building blocks. The project is packaged as a mirror to extend server A! Server B
-
Easier system operation and maintenance
- After containerization, our development and testing environments are highly consistent.
-
More efficient utilization of computing resources
- Docker is kernel-level virtualization that can run many container instances on one physical machine! Server performance can be squeezed to the extreme.
1.4. Basic composition of Docker
Look at the picture carefully, pay attention to the lines, and follow the process
-
Image:
-
The docker image is like a template through which container services can be created.
-
For example: tomcat image -> run command execution -> tomcat01 container (which provides services). Multiple containers can be created through this image, such as tomcat02, tomcat03, etc. (the final service run or project run is in the container)
-
-
Container:
- Docker uses container technology to independently run one or a group of applications, created through images.
- Start, stop, delete, basic commands
- At present, this container can be understood as a simple Linux system.
-
Repository:
- The warehouse is where images are stored
- Warehouses are divided into public warehouses and private warehouses (very similar to git)
- Docker Hub is foreign
- Alibaba Cloud... all have container servers (configured with image acceleration)
2. Docker installation
Environmental preparation
- Requires a little basic knowledge of Linux
- CentOS 7 and above
- We use Xshell] to connect to the remote server for operation
environment view
[root@root /]# uname -r
3.10.0-1160.83.1.el7.x86_64
[root@root /]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"
2.1. Uninstall the old version:
[root@root /]# yum remove docker \
> docker-client \
> docker-client-latest \
> docker-common \
> docker-latest \
> docker-latest-logrotate \
> docker-logrotate \
> docker-engine
Loaded plugins: fastestmirror
No Match for argument: docker
No Match for argument: docker-client
No Match for argument: docker-client-latest
No Match for argument: docker-common
No Match for argument: docker-latest
No Match for argument: docker-latest-logrotate
No Match for argument: docker-logrotate
No Match for argument: docker-engine
No Packages marked for removal
Install required packages:
yum install -y yum-utils
#修改阿里云镜像
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
Are there multiple Docker repositories?
If multiple Docker repositories are enabled, installations or updates performed without specifying a version in the yum install or yum update command will always install the highest version, which may not be suitable for your stability needs.
2.2. Install Docker Engine-Community:
yum install docker-ce docker-ce-cli containerd.io
To install a specific version of Docker Engine-Community, list the available versions in the repository, then select and install:
# 列出并排序可用版本
yum list docker-ce --showduplicates | sort -r
docker-ce.x86_64 3:18.09.1-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.1.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.0.ce-3.el7 docker-ce-stable
Install a specific version by its full package name, which is the package name (docker-ce) plus the version string (second column), starting with the first colon (:) and ending with the first hyphen , separated by a hyphen (-). For example: docker-ce-18.09.1.
# 指定版本安装
yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
Start Docker:
systemctl start docker
Run hello-world:
docker run hello-world
Set the domestic Alibaba Cloud mirror address:
-
Log in: https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors to get the exclusive address
-
Enter /etc/docker/ and execute:
-
tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://【你的专属ID】.mirror.aliyuncs.com"] } EOF
-
Restart the service:
-
systemctl daemon-reload systemctl restart docker
2.3. Uninstall:
# 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
# 删除资源
rm -rf /var/lib/docker
# /var/lib/docker docker的默认资源目录
View the image downloaded by dockers
[root@root /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 19 months ago 13.3kB
2.4hello-world running process:
2.5. The underlying principles of Docker
- Docker is a system with a Client-Server (cs) structure, and the Docker daemon runs on the host. Access from client via Socket!
- Docker-Server receives the instruction from Docker-Client and will execute this command!
2.6. Why Docker is faster than VM:
1. Docker has fewer abstraction layers than virtual machines.
2. Docker uses the host's kernel, and the VM needs to be the Guest OS.
When creating a new container, docker does not need to reload the kernel of an operating system like a virtual machine to avoid booting. The virtual machine loads the Guest OS in minutes, while docker uses the host's operating system, omitting this complex step. process, seconds
3. Docker commonly used commands
3.1. Help command:
docker version # 显示docker版本信息
docker info # 显示docker系统信息,包括镜像和容器数量
docker --help # docker帮助命令
Address: https://docs.docker.com/reference/
3.2. Mirror command:
docker images View native images
[root@root /]# docker images # 查看所有本机镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 19 months ago 13.3kB
REPOSITORY 镜像仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小
# 可选项
-a # 列出所有镜像
-q # 只显示id
docker search search image
$ docker search (name) # 搜索镜像
# 可选项
-f # 根据条件过滤 -f=STARS=3000
docker pull pulls the image
docker pull (name) # 拉取镜像
docker pull mysql:5.7 # 指定版本
# docker pull 镜像名[:tag] ,可选tag,不写默认latest
docker rmi delete image
docker rmi -f id/name # 根据镜像id或名称删除
docker rmi -f id/name id/name id/name # 根据镜像id或名称删除多个
docker rmi -f $(docker images -aq) # 删除全部镜像
3.3. Container command:
Download image
docker pull centos
After the image is started, it becomes a container; view the container through docker ps. If you start a container that has not been deleted, just start it through docker start.
Create and start a container
docker run [可选参数] image
# 参数说明
--name name # 容器名字
-d # 后台启动方式
-i # 使用交互方式运行,进入容器查看内容
-t # 使用交互方式运行,进入容器查看内容
-p # 指定容器端口
-p 主机端口:容器端口
-p 容器端口
容器端口
-P # 随机指定端口
-v 主机目录:容器目录 # 容器卷挂载
-e # 配置环境
# 启动 并进入容器centos
docker run -it centos /bin/bash
[root@root /]# docker run -it centos /bin/bash
[root@e717714491c1 /]#
# 后台启动,给容器命名并映射端口启动
docker run -d -name name -p 主机端口:容器端口 要启动的容器名
View running containers
docker ps # 列出正在运行的容器
-a # 列车曾经运行过的容器
-n=? # 最近运行过的容器
-q # 只显示容器编号
Exit container
exit #退出容器并停止
ctrl+p+q # 退出容器不停止
Delete container
docker rm 容器id # 删除指定id的容器
docker rm -f $(docker ps -aq) # 删除所有容器
docker ps -a -q|xargs docker rm # 删除所有容器
Start and stop containers
docker start 容器id # 启动容器
docker stop 容器id # 停止容器
docker restart 容器id # 重启容器
docker kill 容器id # 杀死容器
4. Other commonly used commands
Background startup command
docker run -d name
# 问题doker ps 发现启动的停止了
#原因:doker容器后台运行,必须要一个前台的进程doker发现没有前台应用就会自动停止
#nginx 容器启动后发现自己没有提供服务,就会自动停止,就是没有程序了
View log
docker logs 参数
-t, --timestamps # 显示时间戳
-f, -follow # 跟踪日志输出
-n, --tail number # 显示日志条数
View process information in the container
docker top 容器id
View mirror source data
docker inspect 容器id
Enter the currently running container
docker exec -it 容器id /bin/bash # 打开新的终端
docker attach 容器id # 进入当前正在运行的终端
# docker exec 进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach 静茹容器正在执行的终端,不会启动新的进程
Copy the files in the container to the host
docker cp 容器id:容器内路径 目标主机路径
Set tags for images
docker tag 镜像id 信息[作者/镜像名:版本号]
summary
Common commands
attach Attach local standard input, output, and error streams to a running container
#当前shell下 attach连接指定运行的镜像
build Build an image from a Dockerfile # 通过Dockerfile定制镜像
commit Create a new image from a container's changes #提交当前容器为新的镜像
cp Copy files/folders between a container and the local filesystem #拷贝文件
create Create a new container #创建一个新的容器
diff Inspect changes to files or directories on a container's filesystem
#查看docker容器的变化
events Get real time events from the server # 从服务获取容器实时时间
exec Run a command in a running container # 在运行中的容器上运行命令
export Export a container's filesystem as a tar archive
#导出容器文件系统作为一个tar归档文件[对应import]
history Show the history of an image # 展示一个镜像形成历史
images List images #列出系统当前的镜像
import Import the contents from a tarball to create a filesystem image #从tar包中导入内容创建一个文件系统镜像
info Display system-wide information # 显示全系统信息
inspect Return low-level information on Docker objects #查看容器详细信息
kill Kill one or more running containers # kill指定docker容器
load Load an image from a tar archive or STDIN #从一个tar包或标准输入中加载一个镜像[对应save]
login Log in to a Docker registry #
logout Log out from a Docker registry
logs Fetch the logs of a container
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
ps List containers
pull Pull an image or a repository from a registry
push Push an image or a repository to a registry
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save one or more images to a tar archive (streamed to STDOUT by default)
search Search the Docker Hub for images
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
version Show the Docker version information
wait Block until one or more containers stop, then print their exit codes
4.1. Install Nginx:
- Installation process
#1. 搜索镜像 search 建议大家去docker搜索,可以看到帮助文档
docker search nginx
#2. 拉取下载镜像 pull
docker pull nginx
#3. 查看是否下载成功镜像
docker images
#4. 运行nginx
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口:容器内部端口
docker run -d --name nginx01 -p 3344:80 nginx
#也就是说我们可以通过公网的3344,访问到docker的80
#5. 查看正在启动的镜像
docker ps
#6. 测试
#curl命令,利用URL规则在命令行下工作的文件传输工具
#如:curl http://www.linux.com,执行后,www.linux.com 的html就会显示在屏幕上了
#下方访问的是3344端口,显示的是nginx的网页代码,测试完毕
[root@root /]# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html {
color-scheme: light dark; }
body {
width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
#7. 进入容器,查看信息
[root@root /]# docker exec -it nginx01 /bin/bash
root@1cf3f5808b4f:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@1cf3f5808b4f:/# cd /etc/nginx
root@1cf3f5808b4f:/etc/nginx# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
#注意nginx.conf,就是配置文件
-
Host port and container internal port and port exposure:
4.2. Install Tomcat:
# 官方的使用
docker run -it --rm tomcat:9.0
# 我们之前的启动都是后台的,停止了容器之后, 容器还是可以查到,docker run -it --rm 一般用来测试,用完就删
# 下载再启动
docker pull tomcat
# 启动运行
docker run -d -p 3344:8080 --name tomcat01 tomcat
# 测试访问没有问题
# 进入容器
docker exec -it tomcat01 /bin/bash
# 发现问题:1.linux命令少了, 2. webapps下内容为空,阿里云净吸纳过默认是最小的镜像,所有不必要的都剔除了,保证最小可运行环境即可
4.3. Install es + kibana:
# es 暴露的端口很多
# es 十分的耗内存
# es 的数据一般需要放置到安全目录! 挂载
# --net somenetwork 网络配置
# 启动elasticsearch
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
[root@root ~]# docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
9f459fa3e96ef66009ea8bb0453edf7392a87b9b91a066c0528c3a849f0a327a
# 如果报错
docker: Error response from daemon: Conflict. The container name "/elasticsearch" is already in use by container "f08b0feb2db6b73dde47a1440c7f6b0f57b1617d99b3da9fe670ffcb3a55819f". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.
#执行:docker network create somenetwork
创建一个名为somenetwork是的网卡配置
# 启动了linux就卡主了,docker stats 查看cpu状态
# 测试一下es成功了
[root@root ~]# curl localhost:9200
{
"name" : "9f459fa3e96e",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "ySZlA6CHRWW--bL21FvnwA",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
# 增加内存限制,修改配置文件 -e 环境配置修改
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
Before modifying memory
After modifying the memory
Use kibanna to link ES
Visualization:
-
portainer
docker run -d -p 8080:9000 \ --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
-
Rancher (CI/CD reuse)
What is a portainer?
Docker graphical interface management tool! Provide a backend panel for us to operate!
# 安装命令
docker run -d -p 8080:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
Visit: http://120.26.10.6:8088 to access the login interface
5. Docker image
5.1. What is a mirror?
An image is a lightweight, executable independent software package used to package software running environments and software developed based on the running environment. It contains everything needed to run a certain software, including code, runtime libraries, and environment variables. and configuration files.
All applications can be directly packaged as docker images and run directly!
How to get the image:
- Download from remote repository
- Someone else copied it to you
- Make a mirror DockerFile yourself
5.2. Docker image loading principle
UnionFs (Union File System)
UnionFs (Union File System): Union File System (UnionFs) is a hierarchical, lightweight and high-performance file system. It supports modifications to the file system to be superimposed layer by layer as a commit, and at the same time, different Directories are mounted into the same virtual file system (unite several directories into a single virtual filesystem). The Union file system is the basis of Docker images. Images can be inherited through layers. Based on the base image (no parent image), various specific application image
features can be made: multiple file systems are loaded at the same time, but from the outside, only one file system can be seen. Union loading superimposes various layers of file systems so that the final file system contains all underlying files and directories.
Docker image loading principle
The docker image actually consists of a layer-by-layer file system, this layer of file system UnionFS.
Boots (boot file system) mainly includes bootloader and Kernel. Bootloader mainly boots and kernel. When Linux first starts, it will add bootfs file system. At the bottom of the Docker image is boots. This layer is the same as our typical Linux/Unix system, including the boot loader and kernel. When the boot loading is completed, the entire kernel is in the memory. At this time, the right to use the memory has been transferred from bootfs to the kernel. At this time, the system will also uninstall bootfs.
rootfs (root file system), on top of bootfs. Contains standard directories and files such as /dev, /proc, /bin, /etc, etc. in a typical Linux system. Rootfs refers to various operating system distributions, such as Ubuntu, Centos, etc.
Usually the CentOS we install into the virtual machine weighs several GB. Why is Docker only 200 MB?
For a streamlined OS, the rootfs can be very small and only needs to include the most basic commands, tools and libraries. Because the bottom layer directly uses the Host's kernel, you only need to provide the rootfs. It can be seen that for different Linux distributions, boots are basically the same, but rootfs will be different, so different distributions can share bootfs.
Virtual machines are on the minute level, and containers are on the second level!
5.4. Hierarchical understanding
layered mirroring
We can download an image and pay attention to the download log output. We can see that it is downloading layer by layer.
Thinking: Why does the Docker image adopt this layered structure?
The biggest benefit, I think, is resource sharing! For example, if multiple images are built from the same Base image, then the host only needs to keep one base image on the disk, and only one base image needs to be loaded into the memory, so that it can serve all containers. , and each layer of the image can be shared.
To view the image layering, you can use the docker image inspect command
#查看分层命令
docker image inspect redis
[
{
"Id": "sha256:7614ae9453d1d87e740a2056257a6de7135c84037c367e1fffa92ae922784631",
"RepoTags": [
"redis:latest"
],
"RepoDigests": [
"redis@sha256:db485f2e245b5b3329fdc7eff4eb00f913e09d8feb9ca720788059fdc2ed8339"
],
"Parent": "",
"Comment": "",
"Created": "2021-12-21T12:42:49.755107412Z",
"Container": "13d25f53410417c5220c8dfe8bd49f06abdbcd69faa62a9b877de02464bb04a3",
"ContainerConfig": {
"Hostname": "13d25f534104",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"6379/tcp": {
}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.12",
"REDIS_VERSION=6.2.6",
"REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.2.6.tar.gz",
"REDIS_DOWNLOAD_SHA=5b2b8b7a50111ef395bf1c1d5be11e6e167ac018125055daa8b5c2317ae131ab"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"redis-server\"]"
],
"Image": "sha256:e093f59d716c95cfce82c676f099b960cc700432ab531388fcedf79932fc81ec",
"Volumes": {
"/data": {
}
},
"WorkingDir": "/data",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {
}
},
"DockerVersion": "20.10.7",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"6379/tcp": {
}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.12",
"REDIS_VERSION=6.2.6",
"REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.2.6.tar.gz",
"REDIS_DOWNLOAD_SHA=5b2b8b7a50111ef395bf1c1d5be11e6e167ac018125055daa8b5c2317ae131ab"
],
"Cmd": [
"redis-server"
],
"Image": "sha256:e093f59d716c95cfce82c676f099b960cc700432ab531388fcedf79932fc81ec",
"Volumes": {
"/data": {
}
},
"WorkingDir": "/data",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 112691373,
"VirtualSize": 112691373,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/ca334263a60756d34c0025092199d4a9723638c3094e8f109c23eb917d3b23de/diff:/var/lib/docker/overlay2/33f6ed74e0c6ee39b6f2865bba496964685fcf1fd77bfb4d3030de57dec8d212/diff:/var/lib/docker/overlay2/bc941d5f01f0c50d8810db8995c5c76d1b208d028670cedbb56114a126155bc9/diff:/var/lib/docker/overlay2/b444556b32389ddf8d3170319384ef4b434d94ee5df66a5f6cddda5c561db239/diff:/var/lib/docker/overlay2/383ab0cf81eaf8a20d811a3fb7a87fce42caed85ceee5fe245372c5e4f696bc8/diff",
"MergedDir": "/var/lib/docker/overlay2/0a3787bc78f7465860ee85120324dedafeb385bc6e73ba441bca9faca15eed3c/merged",
"UpperDir": "/var/lib/docker/overlay2/0a3787bc78f7465860ee85120324dedafeb385bc6e73ba441bca9faca15eed3c/diff",
"WorkDir": "/var/lib/docker/overlay2/0a3787bc78f7465860ee85120324dedafeb385bc6e73ba441bca9faca15eed3c/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f",
"sha256:9b24afeb7c2f21e50a686ead025823cd2c6e9730c013ca77ad5f115c079b57cb",
"sha256:4b8e2801e0f956a4220c32e2c8b0a590e6f9bd2420ec65453685246b82766ea1",
"sha256:529cdb636f61e95ab91a62a51526a84fd7314d6aab0d414040796150b4522372",
"sha256:9975392591f2777d6bf4d9919ad1b2c9afa12f9a9b4d260f45025ec3cc9b18ed",
"sha256:8e5669d8329116b8444b9bbb1663dda568ede12d3dbcce950199b582f6e94952"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
understand:
All Docker images start from a base image layer. When modifications or new content are added, a new image layer will be created on top of the current image layer.
To give a simple example, if you create a new image based on Ubuntu Linux 16.04, this is the first layer of the new image; if you add a Python package to the image, a
second image layer will be created on top of the basic image layer. ; If you continue to add a security patch, a third image layer will be created. The image currently contains 3 image layers, as shown in the figure below (this is just a very simple example for demonstration).
While adding additional image layers, the image always remains a combination of all current images.
It is important to understand that while adding additional image layers, the image always remains a combination of all current images. The figure below shows a simple example. Each image layer contains 3 files, and the image contains 6 files from two image layers.
The image layer in the above picture is slightly different from the previous one. The main purpose is to facilitate the display of files
. The following picture shows a slightly more complicated three-layer image. From the outside, the entire image only has 6 files. This is because the top layer File 7 in is an updated version of file 5.
In this case, the files in the upper mirror layer overwrite the files in the lower mirror layer. This causes the updated version of the file to be added to the image as a new image layer
Docker implements the image layer stack through a storage engine (the new version uses a snapshot mechanism) and ensures that multiple image layers are displayed as a unified file system.
The storage engines available on Linux are AUFS, Overlay2, Device Mapper, Btrfs, and ZFS. As the name implies, each storage engine is based on the corresponding
software system or block device technology in Linux, and each storage engine has its own unique performance characteristics.
Docker only supports windowsfilter on Windows, a storage engine that implements layering and CoW on top of the NTFS file system [1].
The image below shows the same three-layer image as the system display. All mirror layer stacks are merged to provide a unified view to the outside world.
Features
Docker images are read-only, and when the container starts, a new writable layer is loaded on top of the image!
This layer is what we usually call the container layer, and everything below the container is called the mirror layer.
5.5. Commit image (submit your own image)
Package your own image, similar to Linux snapshot operations.
docker commit #提交容器成为一个新的镜像
docker commit -m="信息" -a="作者" 容器id 目标镜像名:[TAG版本号]
test:
#1. 启动一个默认的tomcat
[root@root ~]# docker run -it -p 8080:8080 tomcat
#2. 发现这个默认的tomcat 是没有webapps应用,官方的镜像默认webapps下面是没有文件的!
[root@root ~]# docker exec -it 6a247eda1614 /bin/bash
#3. 将webapps.dist里的所有东西拷贝文件进webapps,并查看
root@6a247eda1614:/usr/local/tomcat# cd webapps
root@6a247eda1614:/usr/local/tomcat/webapps# ls
root@6a247eda1614:/usr/local/tomcat/webapps# cd ..
root@6a247eda1614:/usr/local/tomcat# ls
BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist
CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work
root@6a247eda1614:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@6a247eda1614:/usr/local/tomcat# cd webapps
root@6a247eda1614:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
root@6a247eda1614:/usr/local/tomcat/webapps# exit
exit
#4. 操作过的容器通过commit调教为一个镜像!我们以后就使用我们修改过的镜像即可,而不需要每次都重新拷贝webapps.dist下的文件到webapps了,这就是我们自己的一个修改的镜像。
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[TAG]
docker commit -a="hwt" -m="add webapps app" 6a247eda1614 tomcat02:1.0
[root@root ~]# docker commit -a="hwt" -m="add webapps app" 6a247eda1614 tomcat02:1.0
[root@root ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
#看下方这个tomcat02.1.0就是我们创建的镜像,发布之后再说
tomcat02 1.0 bf96397625ab 8 seconds ago 684MB
nginx latest 605c77e624dd 15 months ago 141MB
tomcat 9.0 b8e65a4d736d 16 months ago 680MB
tomcat latest fb5657adc892 16 months ago 680MB
redis latest 7614ae9453d1 16 months ago 113MB
mysql 5.7 c20987f18b13 16 months ago 448MB
hello-world latest feb5d9fea6a5 19 months ago 13.3kB
centos latest 5d0da3dc9764 19 months ago 231MB
portainer/portainer latest 580c0e4e98b0 2 years ago 79.1MB
elasticsearch 7.6.2 f29a1ee41030 3 years ago 791MB
6. Container data volume
6.1. What is a container data volume?
The idea of docker is to package applications and environments into one image!
If the data is in the container, then if we delete the container, the data will be lost! So we have a need: data can be persisted
For example: MySQL is installed and the container is deleted, which is equivalent to deleting the database and running away! So we have a need: MySQL data can be stored locally!
So we need a technology that can share data between containers! The data generated in the Docker container is synchronized to the local!
This is roll technology! To put it bluntly, it is the mounting of the directory. Mount the directory in our container to Linux!
To summarize in one sentence: container persistence and synchronization operations! Data can also be shared between containers!
6.2. Using data volumes
Method 1: Directly use the command to mount -v
docker run -it -v 主机目录:容器目录
[root@root home]# docker run -it -v /home/ceshi:/home centos /bin/bash
# 启动起来之后可以通过docker inspect 容器id
Test file synchronization:
Continue testing
- Stop container
- Modify files on the host machine
- Start container
- Container data is still synchronized
Advantages: We only need to modify it locally in the future , and it will be automatically synchronized in the container !
Practical combat: Install MySQL
#1. 获取mysql镜像
[root@root home]# docker pull mysql:5.7
#2. 运行容器的时候需要做数据挂载,此处我们挂载了配置文件以及数据目录(有两个哦),同时咱们也配置了mysql的密码
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
-- name 容器名字
[root@iZ2vc28obhvfham8wewhh0Z ~]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql 01 mysql:5.7
#3. 启动成功之后,我们可以在本地使用sqlyog来接入测试
# 测试连接到服务器的3310 --- 3310 和容器内的 3306 映射这个时候就链接到了
#在本地创建一个数据库 查看映射路径发现容器内也增加同步过来了
Even if the container is deleted, the data volume mounted locally is still not missing, which realizes the data persistence function.
6.3. Named and anonymous mounting
Anonymous mount
When
-v
the local directory is not specified, but only the directory in the container is specified, it is mounted anonymously. It will generate a random string name as the local directory name;
# 匿名挂载
[root@root ~]# docker run -d -P --name nginx01 -v /etc/nginx nginx
808f57f0b2761e7dbedc55b7b5f4f2a0a3c6d8f787af28c43eee6cbe397c624f
# 启动之后查看挂载信息,可以看到生成了一个很长的名字
[root@root ~]# docker volume ls
DRIVER VOLUME NAME
local 4a9000076681c93f5c1c68a22184224cba3a5bff78c72a444700d16e85929432
local 59a7bcb1858a64e6f70c1a360e2dd34ac848a4ce2654c9b7ce70832d8030d546
local 5164a418a0559bfe8144dc91783b9b0fe9279285379995a073e963aa0b1f2d85
local a60aefe0bb6c0faf7e95c1a34e98da64faf1aca46c97ff3add7357060fa543b4
# 根据生成的名字查看具体挂载到本地位置目录
[root@root ~]# docker inspect 808f57f0b2761e7dbedc55b7b5f4f2a0a3c6d8f787af28c43eee6cbe397c624f
[
{
"CreatedAt": "2021-03-19T22:50:49+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/65b1f54c7f22614ed5920b623e208bfefc0a6b0bef2b721559bb2e2ce284b851/_data",
"Name": "65b1f54c7f22614ed5920b623e208bfefc0a6b0bef2b721559bb2e2ce284b851",
"Options": null,
"Scope": "local"
}
]
# "Mountpoint" 值就是挂载本地目录。
Named mount
Specify name when mounting
# 指定名称为 juming-guazai
[root@root ~]# docker run -d -P --name nginx02 -v juming-guazai:/etc/nginx nginx
5e04b9325aaf2a3c39ff24a3335f2b3d5e617797e057f445bdae37dc867d308f
# 查看挂载
[root@root ~]# docker volume ls
DRIVER VOLUME NAME
local 4a9000076681c93f5c1c68a22184224cba3a5bff78c72a444700d16e85929432
local 59a7bcb1858a64e6f70c1a360e2dd34ac848a4ce2654c9b7ce70832d8030d546
local 5164a418a0559bfe8144dc91783b9b0fe9279285379995a073e963aa0b1f2d85
local a60aefe0bb6c0faf7e95c1a34e98da64faf1aca46c97ff3add7357060fa543b4
local juming-guazai
# 通过挂载名查看本地具体位置目录
[root@root ~]# docker inspect juming-guazai
[
{
"CreatedAt": "2023-04-22T09:47:24+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-guazai/_data",
"Name": "juming-guazai",
"Options": null,
"Scope": "local"
}
]
All volumes in the docker container, if no directory is specified, are mounted at:/var/lib/docker/volumes/挂载名/_data
Extension: By -v 容器内路径:ro/rw
changing the read and write permissions of the path within the container!
ro readonly #只读
rw readwrite #可读写
docker run -d -P --name nginx02 -v juming-guazai:/etc/nginx:ro nginx
6.4. Data volume container
Data sharing between containers
--volumes-from 父容器
7、Dockerfile
7.1. What is Dockerfile
Dockerfile is a text file used to build an image
Through this script, you can generate images. The images are layer by layer. The script contains commands one by one. Each command is a layer!
step:
- Write a dockerfile
- docker build builds into a mirror
- docker run runs the image
- docker push publish image
# 创建一个dockerfile文件, 名字可以随机
# 文件的内容 指定(大写) 参数
FROM centos
VOLUME ["volume01", "volume02"]
CMD echo "----end----"
CMD /bin/bash
# 这里的每一个命令都是镜像的一层!
Start the container you created
# docker inspect 容器id 查看 Docker 容器的详细信息,包括容器的镜像、名称、状态、容器运行时环境等信息。
[root@root /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4ffeab47d952 30867ff50a2c "/bin/bash" 15 minutes ago Up 15 minutes eloquent_blackwell
5e04b9325aaf nginx "/docker-entrypoint.…" 38 minutes ago Up 38 minutes 0.0.0.0:32769->80/tcp, :::32769->80/tcp nginx02
808f57f0b276 nginx "/docker-entrypoint.…" 55 minutes ago Up 55 minutes 0.0.0.0:32768->80/tcp, :::32768->80/tcp nginx01
[root@root /]# docker inspect 4ffeab47d952
Through testing, it was found that the data was synchronized to the host.
We will use this method a lot in the future, because we usually build our own images!
Assuming that the volume is not mounted when building the image, you need to manually mount the image -v volume name: path in the container!
7.1. Data volume container
Multiple mysql synchronization data!
[root@root home]# docker run -it --name docker01 hwt/centos:1.0
[root@dcddb933ac72 /]# ls -l
total 56
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 360 Apr 22 02:59 dev
drwxr-xr-x 1 root root 4096 Apr 22 02:59 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
.....
drwxr-xr-x 2 root root 4096 Apr 22 02:59 volume01
drwxr-xr-x 2 root root 4096 Apr 22 02:59 volume02
[root@root home]# docker run -it --name docker02 --volumes-from docker01 hwt/centos:1.0
[root@f9f72b54d0ab /]# ls -l
total 56
....
[root@f9f72b54d0ab volume01]# ls
docker01
Test deletion of docker01 to see if docker02 and docker03 can still access this file.
The results are still accessible
Multiple mysql to achieve data sharing
docker run -d -p 3344:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql01 mysql:5.7
docker run -d -p 3344:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql02 --volumes-from mysql01 mysql:5.7
# 这个时候就可以实现连哥哥容器的数据共享
7.3. Dockerfile construction process
know:
- Each keyword command must be capitalized;
- Orders are executed from top to bottom;
#
Indicates comments;- Each command creates and submits a new image layer;
dockerFile is for development. If we want to publish projects and make images in the future, we need to write a dockefile. This file is very simple!
Docker images are gradually becoming the interaction standard for enterprises and must be mastered!
Steps: development, deployment, operation and maintenance... none of them can be missing!
DockerFile: Build file, defines all steps, source code
DockerImages: Build the image generated by DockerFile, and finally publish and run the product!
Docker container: A container is an image that runs to provide a server
Dockerfile is development-oriented. To release a project, you need to create a mirror and write a dockerfile file;
Dockerfile instructions:
FROM # 基础镜像,镜像从这里开始
MAINTAINER # 镜像是谁写的
RUN # docker镜像构建的时候运行的命令
ADD # 给镜像添加内容,添加组件,如果是tar包可以自动解压
WORKDIR # 镜像的工作目录
VOLUME # 挂载卷目录
EXPOSE # 暴露端口配置
CMD # 指定容器启动的时候运行的命令,不可以追加命令 会被替换
ENTRYPOINT # 指定容器启动的时候运行的命令,可以追加命令,不会替换
ONBUILD # 当构建一个被继承的dockerfile时就会触发
COPY # 将文件拷贝到目录中
ENV # 构建的时候设置环境变量
LABEL # 设置镜像的标签
7.4 Practice creating a custom image
instruction
# 编写构建镜像文件
[root@root dockerfile]# vim mydockerfile-centos
[root@root dockerfile]# cat mydockerfile-centos
FROM centos
MAINTAINER hwt<2813068665@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "-----end----"
CMD /bin/bash
[root@root dockerfile]# docker build -f mydockerfile-centos -t mycentos:1.0 .
# 构建镜像
docker build -f 镜像文件 -t 镜像名 .
List local image change history and build information
docker history 镜像id
The difference between CMD and ENTRYPOINT:
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令, 可以追加命令
7.5. Customize tomcat environment mirror centos
-
Prepare the image file tomcat compressed package, jdk compressed package!
-
Write a Dockerfile file with an official name
Dockerfile
. Build will automatically look for this file, so there is no need to specify -f!#1. 创建Dockerfile文件,官方建议名称为Dockerfile #Dockerfile的内容如下: #----------------------------------- # 基础镜像centos FROM centos:7 # 作者信息编写 MAINTAINER hwt<2813068665@qq.com> # 添加jdk,ADD 命令会自动解压到/usr/local目录 ADD jdk-8u361-linux-x64.rpm /usr/local/ # 添加tomcat,ADD 命令会自动解压到/usr/local目录 ADD apache-tomcat-9.0.73.tar.gz /usr/local/ # 安装 vim 命令 RUN yum -y install vim # 设置MYPATH ENV MYPATH /usr/local # 工作目录,引用MYPATH WORKDIR $MYPATH # 配置环境变量:JAVA_HOME环境变量 ENV JAVA_HOME /usr/local/jdk1.8.0_361 # 配置CLASSPATH ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar # 环境变量: tomcat环境变量 ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.73 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.73 # 设置环境变量 分隔符是: ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin # 设置暴露的端口 EXPOSE 8080 # 设置默认命令,这里设置了启动指定目录下的startup.sh程序以及日志 CMD /usr/local/apache-tomcat-9.0.73/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.73/bin/logs/catalina.out #2. 创建一个readme.txt的文件 touch readme.txt
-
Build the image; if the build file is named Dockerfile, you do not need to write the build file location when building the image.
[root@node1 tomcat]# docker build -t mytomcat .
-
Image build successful!
Check whether the local image has a successfully built image
-
Run the image and mount the project directory and log directory at the same time;
[root@root tomcat]# docker run -d -p 9090:8080 --name mytomcat -v /home/hwt2/build/tomcat/test:/usr/local/apache-tomcat-9.0.73/webapps/test -v /home/hwt2/build/tomcat/tomcatlogs:/usr/local/apache-tomcat-9.0.73/logs divtomcat
At this time, you can put the relevant web page under the test project in the mounting directory;
Write web.xml and index.jsp locally for testing
Create new web.xml under WEB-INF
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
</web-app>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
</head>
<body>
6666<br/>
<%
System.out.println("-----666666------");
%>
</body>
</html>
7.6. Release images
Publish to Docker Hub
- Register an account: https://hub.docker.com/
- Log in
[root@root tomcat]# docker login --help
Usage: docker login [OPTIONS] [SERVER]
Log in to a registry.
If no server is specified, the default is defined by the daemon.
Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
[root@root tomcat]# docker login -u hwt6
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
Submit imagedocker push
#修改镜像名 镜像id 新名字
docker tag 169ea7da7330 hwt6/tomcat:1.0
#docker push 文件名/镜像名:版本号
[root@root tomcat]# docker push hwt6/tomcat:1.0
When submitting, it is also submitted according to the level.
Publish to Alibaba Cloud Image
- Log in to Alibaba Cloud
- Open the container image service
- Create namespace
- Create a container image
- push
7.7. Summary
Looking at this picture now, it’s not a big problem. The save and load in the picture are local image compression backups. We usually choose push to upload directly to dockerhub or Alibaba Cloud.
8. Docker network
Clear all images
# 列出当前运行中的镜像
docker ps
#停止运行该id的镜像
docker stop e39146c13894
#删除所有镜像
docker rmi -f $(docker images -aq)
查看本地镜像
docker images
8.1. Docker network ip
View local network information
It can be seen that there are three network card information, lo: local; ens: virtual machine or Alibaba Cloud server address; docker0: docker network address.
The following error is reported and there is no solution for executing the command in the container:
Get the latest package list from the software source and download and install the iproute2 package and its dependencies. apt update && apt install -y iproute2
View the internal network when the docker container is started; start two containers respectively;
docker run -d -P --name tomcat04 tomcat
#查看容器的内部网络地址 ip addr , 发现容器启动的时候会得到一个 eth0@if11 ip地址 docker分配的
[root@root ~]# docker exec -it tomcat04 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
#测试linux能不能ping通容器
[root@root ~]# ping 172.17.0.4
PING 172.17.0.4 (172.17.0.4) 56(84) bytes of data.
64 bytes from 172.17.0.4: icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from 172.17.0.4: icmp_seq=2 ttl=64 time=0.049 ms
64 bytes from 172.17.0.4: icmp_seq=3 ttl=64 time=0.072 ms
64 bytes from 172.17.0.4: icmp_seq=4 ttl=64 time=0.047 ms
64 bytes from 172.17.0.4: icmp_seq=5 ttl=64 time=0.072 ms
64 bytes from 172.17.0.4: icmp_seq=6 ttl=64 time=0.045 ms
^C
--- 172.17.0.4 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 4999ms
rtt min/avg/max/mdev = 0.045/0.058/0.072/0.014 ms
Every time we start a docker container, docker will assign an IP to the docker container. As long as we install docker, there will be a network card docker0 (bridge mode), and the technology used is veth-pair technology!
-
We tested the ip addr and found that there was an extra 10 and 11
-
We started another tomcat05 and found that there were another 24 and 25
-
summary:
我们发现这个容器带来网卡,都是一对对的 veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连 正因为有这个特性 veth-pair 充当一个桥梁,连接各种虚拟网络设备的 OpenStac,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术
-
Let’s try again to see if the containers can ping. Conclusion: we can ping! Draw directly to understand:
If the ping command is not installed in the container, execute: apt-get install inetutils-ping to install the ping command.
Conclusion: tomcat01 and tomcat02 share a router, docker0
When all containers do not specify a network, they are routed by docker0. Docker will assign a default available IP to our container.
summary
Docker uses Linux bridging, and the host is a Docker container bridge docker0
All network interfaces in Docker are virtual, and virtual forwarding is highly efficient! (Transfer files within the intranet!)
As long as the container is deleted, the corresponding pair of bridges will be gone!
8.2、–link
Demand, every time the container or Linux is restarted, the ip will change, and the fixed ip Internet network will become invalid. How to use the service name to connect without considering the ip?
Test using container name to ping
[root@root ~]# docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known
[root@root ~]#
Containers cannot be connected through container names;
How to solve?
[root@root ~]# docker run -d -P --name tomcat09 --link tomcat07 tomcat
8a834bd9c3c401ecfc454ceb322e3f9cc8ffccdcc04662d69f6483ea80e4a28b
[root@root ~]# docker exec -it tomcat09 ping tomcat07
PING tomcat07 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: icmp_seq=0 ttl=64 time=0.174 ms
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.130 ms
^C--- tomcat07 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.130/0.152/0.174/0.000 ms
# 但是反向却无法链接通!!!
Tomcat09 can link to tomcat07 through the container name. The principle is that -link configures tomcat07 ip information in its own container hosts file through tomcat09!
[root@root ~]# docker exec -it tomcat09 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 tomcat07 59106d96228b
172.17.0.5 8a834bd9c3c4
The essence is to modify the host mapping, and –link has been abandoned; it is recommended to use a custom network implementation!
8.3. Customized network
View local docker network information
[root@root ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
ba12df0f9aa6 bridge bridge local
e379cdacfac2 es bridge local
0d4f6c0df3b3 host host local
5b531cef8601 none null local
e52ae9b4207b somenetwork bridge local
- bridge: bridge (default, use bridge if you create it yourself)
- host: shared with the host
- none: Do not configure the network
# 删除所有容器
[root@root ~]# docker rm -f $(docker ps -aq)
# 我们直接启动的命令 --net bridge 这个就相当于docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --net bridge --name tomcat01 tomcat
# docker0 特点,默认的,域名不能访问 --link可以打通连接
# 所以我们可以指定自定义的网络
# 通过docker network --help
[root@root ~]# docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
Run 'docker network COMMAND --help' for more information on a command.
Create a custom network
docker create
[root@root ~]# docker network create -d bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
9b2c349093073aa9527b4ef8f7cc3344ad224b9b9eb2c3f522c7fcb6fd0322b3
-d --driver 网络模式
--subnet 子网
--gateway 网关
---------------------------------------------
# 命令参数详解
[root@root ~]# docker network create --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which to copy the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment
View the network we created
[root@root ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
ba12df0f9aa6 bridge bridge local
e379cdacfac2 es bridge local
0d4f6c0df3b3 host host local
9b2c34909307 mynet bridge local
5b531cef8601 none null local
e52ae9b4207b somenetwork bridge local
View custom networks
The custom network is created!
After the container is started, the network can be configured under the custom network, which solves the shortcomings of –link!
# 启动两个容器
[root@root ~]# docker run -d -P --net mynet --name tomcat01-net-01 tomcat
[root@root ~]# docker run -d -P --net mynet --name tomcat01-net-02 tomcat
# 不同容器同处于同一网络下mynet,维护好了容器间的关系。
root@24420c5c2183:/usr/local/tomcat# read escape sequence
[root@root ~]# docker exec -it tomcat01-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3): 56 data bytes
64 bytes from 192.168.0.3: icmp_seq=0 ttl=64 time=0.154 ms
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.138 ms
^C^C--- 192.168.0.3 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.111/0.130/0.154/0.000 ms
View mynet network information
[root@node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
8d5e54eaae69 bridge bridge local
3452d41b8d68 host host local
30d7111860cf mynet bridge local
c98ef8bfc64b none null local
[root@node1 ~]# docker network inspect 30d7111860cf
Different clusters can use different networks to ensure the security and health of the cluster network;
For example, the Redis cluster is under the 192.160.0.0/16 network segment, and the mysql cluster is under the 192.161.0.0/16 network segment.
8.4. Network connectivity
Scenes:
Test to connect tomcat01 and mynet
Solution: Use
docker network connect
implementation.
#语法:docker network connect [OPTIONS] NETWORK CONTAINER
#1. 之前删除的tomcat01和tomcat02创建好
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat02 tomcat
#2. 打通tomcat01和mynet
docker network connect mynet tomcat01
#3. 查看网络配置,如下图所示:
docker network inspect mynet
# 要将tomcat01 连通 tomcat—net-01 ,连通就是将 tomcat01加到 mynet网络
# 一个容器两个ip(tomcat01)
Test connectivity:
[root@root ~]# docker exec -it tomcat01-net-01 ping tomcat01
PING tomcat01 (192.168.0.4): 56 data bytes
64 bytes from 192.168.0.4: icmp_seq=0 ttl=64 time=0.156 ms
64 bytes from 192.168.0.4: icmp_seq=1 ttl=64 time=0.120 ms
64 bytes from 192.168.0.4: icmp_seq=2 ttl=64 time=0.116 ms
64 bytes from 192.168.0.4: icmp_seq=3 ttl=64 time=0.114 ms
^C--- tomcat01 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.114/0.127/0.156/0.000 ms
9. Redis cluster deployment
# 创建网卡
docker network create redis --subnet 172.38.0.0/16
# 通过脚本创建六个redis配置
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
# 创建结点1
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#创建结点2
docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#创建结点3
docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#创建结点4
docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#创建结点5
docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#创建结点6
docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
# 创建集群
[root@root conf]# docker exec -it redis-1 /bin/sh
/data # ls
appendonly.aof nodes.conf
/data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:637
79 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.38.0.15:6379 to 172.38.0.11:6379
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
M: 53eab5178492fd576f5f3d86b1c6a5400dd5b820 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
M: 9ac04371d9db47317ea7f50012b350d55c4ef5e3 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
M: e749dd5cbf37951ec8822352d92961fc01411e90 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
S: dbbef8c10be71c8e45d360fdd035d16ddf65f204 172.38.0.14:6379
replicates e749dd5cbf37951ec8822352d92961fc01411e90
S: e8b9337658171043ed9ef6b351a71f397b69b3bc 172.38.0.15:6379
replicates 53eab5178492fd576f5f3d86b1c6a5400dd5b820
S: a988d3ac588e4ff564092470771b9541d253cc51 172.38.0.16:6379
replicates 9ac04371d9db47317ea7f50012b350d55c4ef5e3
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
..
>>> Performing Cluster Check (using node 172.38.0.11:6379)
M: 53eab5178492fd576f5f3d86b1c6a5400dd5b820 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: a988d3ac588e4ff564092470771b9541d253cc51 172.38.0.16:6379
slots: (0 slots) slave
replicates 9ac04371d9db47317ea7f50012b350d55c4ef5e3
M: e749dd5cbf37951ec8822352d92961fc01411e90 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: dbbef8c10be71c8e45d360fdd035d16ddf65f204 172.38.0.14:6379
slots: (0 slots) slave
replicates e749dd5cbf37951ec8822352d92961fc01411e90
S: e8b9337658171043ed9ef6b351a71f397b69b3bc 172.38.0.15:6379
slots: (0 slots) slave
replicates 53eab5178492fd576f5f3d86b1c6a5400dd5b820
M: 9ac04371d9db47317ea7f50012b350d55c4ef5e3 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
--------------------测试-------------------------------
127.0.0.1:6379> set a b
-> Redirected to slot [15495] located at 172.38.0.13:6379
OK
172.38.0.13:6379> get a
Could not connect to Redis at 172.38.0.13:6379: Host is unreachable
(33.82s)
not connected>
/data # redis-cli -c
127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.38.0.14:6379
"b"
Test to delete the main image after saving the data:
[root@root ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d8dce4527ba6 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 12 minutes ago Up 12 minutes 0.0.0.0:6376->6379/tcp, :::6376->6379/tcp, 0.0.0.0:16376->16379/tcp, :::16376->16379/tcp redis-6
fc84445e7601 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 13 minutes ago Up 13 minutes 0.0.0.0:6375->6379/tcp, :::6375->6379/tcp, 0.0.0.0:16375->16379/tcp, :::16375->16379/tcp redis-5
5d151352d7cd redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 13 minutes ago Up 13 minutes 0.0.0.0:6374->6379/tcp, :::6374->6379/tcp, 0.0.0.0:16374->16379/tcp, :::16374->16379/tcp redis-4
b69bbff6e0e6 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 13 minutes ago Up 13 minutes 0.0.0.0:6373->6379/tcp, :::6373->6379/tcp, 0.0.0.0:16373->16379/tcp, :::16373->16379/tcp redis-3
add6c2b74c1c redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 14 minutes ago Up 14 minutes 0.0.0.0:6372->6379/tcp, :::6372->6379/tcp, 0.0.0.0:16372->16379/tcp, :::16372->16379/tcp redis-2
e73a43d175f3 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 14 minutes ago Up 14 minutes 0.0.0.0:6371->6379/tcp, :::6371->6379/tcp, 0.0.0.0:16371->16379/tcp, :::16371->16379/tcp redis-1
[root@root ~]# docker stop redis-3
redis-3
[root@root ~]#
It will become easier after using docker
10. SpringBoot microservice packaging Docker image
-
Build springboot project
-
Packaged application
-
Write Dockerfile
FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java", "-jar", "/app.jar"]
-
-
Build image
-
Release to run!
# 把jar包构建为镜像 docker build -t hwt666 . # 运行docker镜像 docker run -d -P --name hwt-springboot-web hwt666 # 测试访问 [root@root idea]# curl localhost:32781/hello hello docker[root@root idea]#
Install docker on four machines
Same as our stand-alone installation
Tips: xshell directly synchronizes operations, saving time!
Swarm cluster construction
Docker Engine 1.12 introduces swarm mode that enables you to create a cluster of one or more Docker Engines called a swarm. A swarm consists of one or more nodes: physical or virtual machines running Docker Engine 1.12 or later in swarm mode.
There are two types of nodes: managers and workers.
docker swarm init --help
ip addr # 获取自己的ip(用内网的不要流量)
[root@localhost ~]# docker swarm init --advertise-addr 192.168.29.130
Swarm initialized: current node (lx0lbv9i1cui04kqeiej1pbjb) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-0tp5ijg39u8gn8jnceymrfe6lc8g9ca2w2thbk1922vhkh4mp8-7kr1qko1dgrz75g34axvn9f6i 192.168.29.130:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
initialize nodedocker swarm init
docker swarm join joins a node!
# 获取令牌
docker swarm join-token manager
docker swarm join-token worker
[root@localhost ~]# docker swarm join --token SWMTKN-1-0tp5ijg39u8gn8jnceymrfe6lc8g9ca2w2thbk1922vhkh4mp8-7kr1qko1dgrz75g34axvn9f6i 192.168.29.130:2377
This node joined a swarm as a worker.
Build all the nodes at the back
Two possible errors and their solutions:
-
The master node firewall is not turned off
#报错信息 Error response from daemon: rpc error: code = Unavailable desc = all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: Error while dialing dial tcp 192.168.0.108:2377: connect: no route to host" # 查看当前防火墙状态 [root@localhost ~]# systemctl status firewalld.service # 关闭防火墙 [root@localhost ~]# systemctl stop firewalld.service # 永久停止防火墙 [root@localhost ~]# systemctl disable firewalld.service
-
Port not open
# 报错信息 [root@localhost ~]# docker swarm join --token SWMTKN-1-0tp5ijg39u8gn8jnceymrfe6lc8g9ca2w2thbk1922vhkh4mp8-7fh11rblokyz15sa7f26hwimy 192.168.29.130:2377 Error response from daemon: manager stopped: can't initialize raft node: rpc error: code = Unknown desc = could not connect to prospective new cluster member using its advertised address: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 192.168.29.133:2377: connect: no route to host" # 在docker4上查看2377端口开放情况,发现没有任何端口 [root@localhost ~]# firewall-cmd --zone=public --list-ports # 在docker4上开放2377端口 [root@localhost ~]# firewall-cmd --zone=public --add-port=2377/tcp --permanent success [root@localhost ~]# firewall-cmd --reload success
100 units!
- Generate master node init
- Join (manager, worker)