目录
4.7.2:docker compose:利用yaml快速启动容器
1:架构
1.1、docker客户端:操作docker主机的一端,通过发送不同命令给docker主机的进程Docker Daemon。
1.2、Docker主机:安装了Docker环境的就是Docker主机,只要安装了Docker就会有一个Docker Daemon进程一直在后台运行,用来处理docker客户端发来的请求。
1.3、应用市场:将所有应用都放在应用市场里(mysql、redis等等)。
------------------------------------------------------------------
docker pull redis 我想要获取redis的应用,那就需要在客户端发送命令docker pull redis,到Docker主机中的进程Docker Daemon,然后这个进程就会向应用市场拉取镜像,放到docker主机中。
docker run redis:想启动这个应用,他会优先在Docker主机中寻找这个镜像,然后根据这个镜像启动一个应用(如果在Docker主机找不到镜像,他会到应用市场下载一个镜像到Docker主机中,然后再根据镜像启动应用·)。
启动的这个应用,称为容器。我们可以启动多个应用(容器),每个容器就是运行中的应用
docker build xxx:自己想制作镜像,之前都是通过应用市场拉取公共镜像,如果我们想自己制作镜像,那我们就需要通过docker build xxx命令发送给Docker Daemon,然后Docker Daemon进程就会帮我制造一个镜像到docker主机中。
docker push xxx:如果我们希望把我们制作的镜像交给应用市场保存,那就可以docker push xxx,这样其他人(张三、李四、王五就可以获取到这个应用了)
build:构建自己的应用
分享:自己build-自己push-别人pull
运行:run
2:理解容器
传统部署:他们共享一个环境,如果其中一个应用出现问题比如出现内存泄漏,那这个应用就会无限占用空间,从而导致其他应用受到牵连。
虚拟化部署:开几个虚拟机,互相不影响,但是缺点是虚拟机会有完整的操作系统,从而比较笨重。
容器部署:同虚拟化部署一样具有隔离机制,每个应用可以共享操作系统内核(但是文件系统、cpu、内存、进程都是隔离的),可以看做轻量化的虚拟机
3:云服务器安装Docker
先购买云服务器
Docker: Accelerated Container Application Development
安装docker
官网安装介绍CentOS 操作系统 |Docker 文档
如果是香港服务器,就完全按照官网命令来最好,不需要配镜像这些
页面要选择好我们安装的类型,因为我们订购的云服务器是centos所以这里也选centos
官网网站上有安装步骤介绍,复制官网提供的命令即可
卸载旧版本docker
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
配置下载源(这里用的是阿里的镜像,因为官网的有点慢)
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装docker
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
启动docker
sudo systemctl start docker
启动完事之后我们要再输入一个命令(必要配置,非官网)
systemctl enable docker
配置镜像源:因为docker默认会从dockerhub下载比较慢,所以可以配置镜像(必要配置,非官网)
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors":["https://mirror.ccs.tencentyun.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
查看docker中正在运行的应用(可以发现没有任何应用运行,因为刚开始)
docker ps
不知道命令:可以在后面加 --help他会有说明,比如docker run --help
4:命令操作
1、镜像操作
实验要求:启动一个nginx,并将它的首页改为自己的页面,发布出去,让所有人都可以使用。
4.1:下载镜像:docker pull
检索:docker search nginx
下载:docker pull ngnix这种下载方式默认是下载最新版
如果我们想下载指定版本,到hubdocker.com去找指定版本docker pull ngnix:1.26.0
列表:docker images (可以查看到我们所下载的所有镜像)
删除:docker rmi 【镜像名字】 (删除某一个镜像)
4.2:启动容器:docker run
运行:docker run ngnix(本地执行 docker run nginx
命令如果本地环境中没有名为 nginx
的镜像,那么 Docker会自动尝试从Docker Hub拉取这个镜像)
运行后就会看到如下图,不要关闭,关闭的话服务就会停止了。复制一个会话。
复制一个会话。进行另外操作
查看:docker ps(查看正在运行的容器)--docker run ngnix会给这个容器起随机名字name
这样要一直挂着不太方便,所以可以用其他的run启动(图中写错了,前面是外部端口后面是内部)
docker run -d --name mynginx-p 80:80 nginx
解释:
-d 后台启动,这样就不会一直占着。
--name myngin 自定在容器的名字,如果不自定义就会随机起个容器名
-p 80:80 端口映射,如果不设置端口映射,我们在其他电脑访问不到。这个就相当于docker对外暴露一个外部端口,然后这个外部端口再映射到内部。
-e环境变量,在hub.docker拉完镜像启动后,要看他的文档,启动要不要加参数
根据公网ip访问下启动的nginx容器,发现可以访问到,因为我们开启了端口映射。
4.3:文件映射 (目录挂载和卷映射)
4.3.1:前言(修改页面):exec进入容器直接修改
我们想修改,访问nginx的访问页面怎么办?
1:先进入容器文件系统,然后修改nginx所在的html文件
进入:docker exec
容器就相当于是一个linux文件系统,我们操作这个linux系统怎么办?
用这个:docker exec -it mynginx /bin/bash
(进入容器就用不了docker命令了,docker命令只有在外部用,如果想从容器退出到外部可以用ctrl+D)
先进入cd /usr/share/nginx/html/ 然后对这个html修改下就可以了
4.3.2:目录挂载
把内部文件和主机外部文件进行映射,修改外部文件就会修改到内部文件,这样就不用进入内部了。
上面这个做法有点麻烦,因为我们每次想要修改都要进入容器内部有点麻烦
docker run -d -p 80:80 -v /app/nghtml:/usr/share/nginx/html --name app01 nginx
访问公网,就发现首页变成了刚刚设置的2222
内部文件和映射的外部文件,是双向映射的,修改外部影响内部,修改内部影响外部。
4.3.3:卷映射
3:卷映射:上面那种方式他会自动帮我们创建文件夹但是不会创建文件,现在我希望他一开始就帮我创建一个一模一样内容的文件,如果想改变再去修改这个映射文件。
docker run -d -p 99:80 -v nghtml:/usr/share/nginx/html --name app02 nginx
生成的卷固定的位置是 /var/lib/docker/volumes/<volume-name>
如上图我修改了外部文件的index.html即卷文件
现在我进入容器内部,发现内部文件也被随着修改了
然后访问试试:http://150.109.147.146:99/--------发现样式改了
4.4:自定义网络
容器之间的访问:每启动一个容器都会为这个容器分配唯一id,进入一个容器使用另一个的(容器ip+容器端口)可以进行访问。缺点:ip由于各种原因发生变化,所以用域名。
创建自定义网络,容器名就是稳定域名。
docker network create mynet
启动两个容器(要使用刚刚自定义的网络--network mynet)
docker run -d --name app01 --network mynet -p 80:80 nginx
docker run -d --name app02 --network mynet -p 99:80 nginx
进入容器01
docker exec -it app1 bash
容器01调用容器02
curl http://app02:80
4.5:针对修改,生成镜像和保存镜像文件
对镜像进行了修改,然后再生成一个镜像
docker commit -m"updatehtml" (生成一个新镜像,-m后面是注释)
保存文件:把上面保存的镜像,保存为一个文件(这里为tar)
别人想通过镜像文件获取镜像:
我们可以把这个tar文件发给别人,然后别人有了这个tar文件后可以通过docker load -i mynginx.tar把这个镜像加载过来
4.6:分享到hub.docker
先网页注册账号,244.***@qq.com,密码 65...t
输入docker login 再依次输入注册过的账号密码
docker tag mynginx:v1.0 1217544/mynginx:v1.0 (mynginx:v1.0是本地就有的镜像,1217544/mynginx:v1.0是用户名+准备腿给远程起的名字)
docker push 1217544/mynginx:v1.0 (推送给远程,后面这个是刚刚起的名字)
个人资料里就有了刚刚推上来的镜像
如果别人想拉,就搜索这个镜像就好了。docker pull 1217544/mynginx:v1.0
4.7:容器一键启动 docker compose
4.7.1:前言
拉别人镜像,然后run。只需要关注端口映射、配置文件、环境变量。
docker network create blog
(记住要先部署mysql、然后在部署项目)
docker run -d -p 8080:80 -e WORDPRESS_DB_HOST=mysql -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=123456 -e WORDPRESS_DB_NAME=wordpress -v wordpress:/var/www/html --restart always --name wordpress-app --network blog wordpress:latest
docker run -d \ --name mysql \ --network blog \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=123456 \ -e MYSQL_DATABASE=wordpress \ -v mysql-data:/var/lib/mysql \ -v /app/myconf:/etc/mysql/conf.d \ --restart always \ mysql:8.0
以上是部署了wordpress博客系统项目,和mysql环境。
但是缺点:如果换个机器,还想想要再部署这两个,还要重新写这两条命令麻烦。
4.7.2:docker compose:利用yaml快速启动容器
如果有多个服务,里面会涉及很多参数,如果对每个服务进行单独run一下就很麻烦。所以我们把多个服务的命令和参数放在yaml配置文件里进行配置,这个yaml文件就相当于多个run命令的集合。然后用docker compose -f compose.yaml up -d就可以一次性启动多个容器了,不需要我们一条一条敲run命令了然后还可以对这个yaml重复利用。
配置文件定义一些顶级元素即可(主要配前4个重要的就行)
yaml配置查参考官网 指定项目名称 |Docker 文档
name: myblog
services:
mysql:
container_name: mysql
image: mysql:8.0
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=wordpress
volumes:
- mysql-data:/var/lib/mysql
- /app/myconf:/etc/mysql/conf.d
restart: always
networks:
- blog
wordpress:
image: wordpress
ports:
- "8080:80"
environment:
- WORDPRESS_DB_HOST=mysql
- WORDPRESS_DB_USER=root
- WORDPRESS_DB_PASSWORD=123456
- WORDPRESS_DB_NAME=wordpress
volumes:
- wordpress:/var/www/html
networks:
- blog
depends_on:
- mysql
volumes:
mysql-data:
wordpress:
networks:
blog:
利用yaml配置文件启动容器:
docker compose up
上线:(适合首次启动)
docker compose -f compose.yaml up -d
下线:下线还是会保留卷,如果需要删除卷需要添加参数
docker compose -f compose.yaml down
启动容器
docker-compose start X1 X2 X3
停止容器
docker compose stop X1 X2 X3
效果
4.8:镜像快速制作 dockerfile
我们往常都是通过hub.docker用别人的镜像,如果我们想自己制作镜像怎么办?
我们有一个app.jar,我们要为他编写一个镜像。首先要把这个app.jar上传至服务器,在这个位置编写镜像配置文件:主要包含(基础环境、软件包、启动命令)
vim Dockerfile
文件内容是:
FROM openjdk:17
LABEL author=hf
COPY app.jar /app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
构建镜像:docker build -f Dockerfile -t myjavaapp:1.0 .
docker分层机制:比如有一个镜像,然后再这个镜像的基础上加一些功能,再生成第二个镜像。这两个镜像中都有jdk17,那么这两个镜像会共用一个jdk17,不会生成两个。从而节省资源。
4.9:其他命令
查看:docker ps -a(查看所有容器,包括已经停止的)
停止:docker stop
启动:docker start
重启:docker restart
状态:docker stats + 运行容器ID(查看启动容器的状态)
日志:docker logs + 运行容器ID
删除:docker rm+运行容器ID(在删除之前需要停止容器)
删除所有容器:docker rm -f $(docker ps -aq)
5:问题
docker中run和start的区别
docker run 后面跟的是镜像,是利用镜像,生成容器并启动容器。
而docker start后面跟的是容器,他是启动一个之前生成过的容器。
内部外部端口映射,内部端口和外部端口号可以重复吗?
答案:内部端口号可以重复,外部不可以。内部每一个容器都可以有一个相同的端口号,因为每个容器都相当于是隔离的,所以他们有同一个端口号是可以的。外部端口只能有一个。
docker如果是已经运行了,那还能执行命令吗?
可以,docker exec -it mynginx /bin/bash,每个容器都相当于独立的虚拟机,也就是Linux文件系统,我们想操作这个系统可以通过docker exec执行
docker compose start和docker compose up区别?
docker-compose up是下载并运行,
适合首次启动,他的参数是根据配置文件来的。docker-compose start用于
启动已有的容器,如果配置改了,然后又停止,再次启动还是改动后的配置,而不是初始的yaml文件
一键启动超多中间件:
docker compose -f compose.yaml up -d (这个命令就相当于run多个服务,里面的参数是根据官网找的,下载并运行)
name: devsoft
services:
redis:
image: bitnami/redis:latest
restart: always
container_name: redis
environment:
- REDIS_PASSWORD=123456
ports:
- '6379:6379'
volumes:
- redis-data:/bitnami/redis/data
- redis-conf:/opt/bitnami/redis/mounted-etc
- /etc/localtime:/etc/localtime:ro
mysql:
image: mysql:8.0.31
restart: always
container_name: mysql
environment:
- MYSQL_ROOT_PASSWORD=123456
ports:
- '3306:3306'
- '33060:33060'
volumes:
- mysql-conf:/etc/mysql/conf.d
- mysql-data:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
rabbit:
image: rabbitmq:3-management
restart: always
container_name: rabbitmq
ports:
- "5672:5672"
- "15672:15672"
environment:
- RABBITMQ_DEFAULT_USER=rabbit
- RABBITMQ_DEFAULT_PASS=rabbit
- RABBITMQ_DEFAULT_VHOST=dev
volumes:
- rabbit-data:/var/lib/rabbitmq
- rabbit-app:/etc/rabbitmq
- /etc/localtime:/etc/localtime:ro
opensearch-node1:
image: opensearchproject/opensearch:2.13.0
container_name: opensearch-node1
environment:
- cluster.name=opensearch-cluster # Name the cluster
- node.name=opensearch-node1 # Name the node that will run in this container
- discovery.seed_hosts=opensearch-node1,opensearch-node2 # Nodes to look for when discovering the cluster
- cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2 # Nodes eligibile to serve as cluster manager
- bootstrap.memory_lock=true # Disable JVM heap memory swapping
- "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m" # Set min and max JVM heap sizes to at least 50% of system RAM
- "DISABLE_INSTALL_DEMO_CONFIG=true" # Prevents execution of bundled demo script which installs demo certificates and security configurations to OpenSearch
- "DISABLE_SECURITY_PLUGIN=true" # Disables Security plugin
ulimits:
memlock:
soft: -1 # Set memlock to unlimited (no soft or hard limit)
hard: -1
nofile:
soft: 65536 # Maximum number of open files for the opensearch user - set to at least 65536
hard: 65536
volumes:
- opensearch-data1:/usr/share/opensearch/data # Creates volume called opensearch-data1 and mounts it to the container
- /etc/localtime:/etc/localtime:ro
ports:
- 9200:9200 # REST API
- 9600:9600 # Performance Analyzer
opensearch-node2:
image: opensearchproject/opensearch:2.13.0
container_name: opensearch-node2
environment:
- cluster.name=opensearch-cluster # Name the cluster
- node.name=opensearch-node2 # Name the node that will run in this container
- discovery.seed_hosts=opensearch-node1,opensearch-node2 # Nodes to look for when discovering the cluster
- cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2 # Nodes eligibile to serve as cluster manager
- bootstrap.memory_lock=true # Disable JVM heap memory swapping
- "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m" # Set min and max JVM heap sizes to at least 50% of system RAM
- "DISABLE_INSTALL_DEMO_CONFIG=true" # Prevents execution of bundled demo script which installs demo certificates and security configurations to OpenSearch
- "DISABLE_SECURITY_PLUGIN=true" # Disables Security plugin
ulimits:
memlock:
soft: -1 # Set memlock to unlimited (no soft or hard limit)
hard: -1
nofile:
soft: 65536 # Maximum number of open files for the opensearch user - set to at least 65536
hard: 65536
volumes:
- /etc/localtime:/etc/localtime:ro
- opensearch-data2:/usr/share/opensearch/data # Creates volume called opensearch-data2 and mounts it to the container
opensearch-dashboards:
image: opensearchproject/opensearch-dashboards:2.13.0
container_name: opensearch-dashboards
ports:
- 5601:5601 # Map host port 5601 to container port 5601
expose:
- "5601" # Expose port 5601 for web access to OpenSearch Dashboards
environment:
- 'OPENSEARCH_HOSTS=["http://opensearch-node1:9200","http://opensearch-node2:9200"]'
- "DISABLE_SECURITY_DASHBOARDS_PLUGIN=true" # disables security dashboards plugin in OpenSearch Dashboards
volumes:
- /etc/localtime:/etc/localtime:ro
zookeeper:
image: bitnami/zookeeper:3.9
container_name: zookeeper
restart: always
ports:
- "2181:2181"
volumes:
- "zookeeper_data:/bitnami"
- /etc/localtime:/etc/localtime:ro
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
kafka:
image: 'bitnami/kafka:3.4'
container_name: kafka
restart: always
hostname: kafka
ports:
- '9092:9092'
- '9094:9094'
environment:
- KAFKA_CFG_NODE_ID=0
- KAFKA_CFG_PROCESS_ROLES=controller,broker
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://0.0.0.0:9094
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://119.45.147.122:9094
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- ALLOW_PLAINTEXT_LISTENER=yes
- "KAFKA_HEAP_OPTS=-Xmx512m -Xms512m"
volumes:
- kafka-conf:/bitnami/kafka/config
- kafka-data:/bitnami/kafka/data
- /etc/localtime:/etc/localtime:ro
kafka-ui:
container_name: kafka-ui
image: provectuslabs/kafka-ui:latest
restart: always
ports:
- 8080:8080
environment:
DYNAMIC_CONFIG_ENABLED: true
KAFKA_CLUSTERS_0_NAME: kafka-dev
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
volumes:
- kafkaui-app:/etc/kafkaui
- /etc/localtime:/etc/localtime:ro
nacos:
image: nacos/nacos-server:v2.3.1
container_name: nacos
ports:
- 8848:8848
- 9848:9848
environment:
- PREFER_HOST_MODE=hostname
- MODE=standalone
- JVM_XMX=512m
- JVM_XMS=512m
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=nacos-mysql
- MYSQL_SERVICE_DB_NAME=nacos_devtest
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_USER=nacos
- MYSQL_SERVICE_PASSWORD=nacos
- MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
- NACOS_AUTH_IDENTITY_KEY=2222
- NACOS_AUTH_IDENTITY_VALUE=2xxx
- NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789
- NACOS_AUTH_ENABLE=true
volumes:
- /app/nacos/standalone-logs/:/home/nacos/logs
- /etc/localtime:/etc/localtime:ro
depends_on:
nacos-mysql:
condition: service_healthy
nacos-mysql:
container_name: nacos-mysql
build:
context: .
dockerfile_inline: |
FROM mysql:8.0.31
ADD https://raw.githubusercontent.com/alibaba/nacos/2.3.2/distribution/conf/mysql-schema.sql /docker-entrypoint-initdb.d/nacos-mysql.sql
RUN chown -R mysql:mysql /docker-entrypoint-initdb.d/nacos-mysql.sql
EXPOSE 3306
CMD ["mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
image: nacos/mysql:8.0.30
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=nacos_devtest
- MYSQL_USER=nacos
- MYSQL_PASSWORD=nacos
- LANG=C.UTF-8
volumes:
- nacos-mysqldata:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
ports:
- "13306:3306"
healthcheck:
test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
interval: 5s
timeout: 10s
retries: 10
prometheus:
image: prom/prometheus:v2.52.0
container_name: prometheus
restart: always
ports:
- 9090:9090
volumes:
- prometheus-data:/prometheus
- prometheus-conf:/etc/prometheus
- /etc/localtime:/etc/localtime:ro
grafana:
image: grafana/grafana:10.4.2
container_name: grafana
restart: always
ports:
- 3000:3000
volumes:
- grafana-data:/var/lib/grafana
- /etc/localtime:/etc/localtime:ro
volumes:
redis-data:
redis-conf:
mysql-conf:
mysql-data:
rabbit-data:
rabbit-app:
opensearch-data1:
opensearch-data2:
nacos-mysqldata:
zookeeper_data:
kafka-conf:
kafka-data:
kafkaui-app:
prometheus-data:
prometheus-conf:
grafana-data: