docker-笔记
安装Docker-CE
https://developer.aliyun.com/mirror/docker-ce?spm=a2c6h.13651102.0.0.3e221b11NLNZGM
https://developer.aliyun.com/article/110806
使用官方安装脚本自动安装 (仅适用于公网环境)
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
CentOS 7 (使用yum进行安装)
# step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 更新并安装 Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 4: 开启Docker服务
systemctl start docker
# 查看docker版本
docker version
# 开机启动
systemctl enable docker
配置镜像
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io
sudo systemctl daemon-reload
sudo systemctl restart docker
常用命令
docker ps // 查看运行的容器
docker ps -a // 查看曾经运行过的容器
docker pull // 从仓库拉取一个容器
docker images // 查看当前镜像
docker create nginx //创建一个容器 返回一个id
docker start xxx // 启动
docker restart xxx // 重新启动
docker run hello-world // run 会尝试启动一个容器,没有会自动拉取镜像,创建并启动
-d 后台启动
-p 容器内端口映射到宿主机端口 宿主机端口:容器内端口
-c CPU份额
-v 目录映射 宿主机目录:容器内目录
-m 内存限制
--memory-swap 内存交换限制
--blkio-weight IO权重
--name 设置一个容器的名字
--restart=always 重启策略
no:不重启
on-failure:退出状态非0时重启
always:始终重启
docker pause 容器ID // 暂停
docker unpause 容器ID // 取消暂停
docker stop 容器ID // 完全停止
docker rm 容器ID //移除一个容器,不能移除正在运行的容器
docker rm -f 容器ID // 强制移除一个容器
docker logs 容器ID // 查看日志
docker logs -f 容器ID //监听日志
# 和容器做交互 用bash方式
docker exec -it 容器ID /bin/bash
批量操作技巧
# 停用全部运行中的容器:
docker stop $(docker ps -q)
# 删除全部容器
docker rm $(docker ps -aq)
# 删除所有镜像
docker rmi docker images -q
# 按条件删除镜像
- 删除没有tag的镜像
docker rmi $(docker images -q | awk '/^<none>/ { print $3 }')
- 镜像名包含关键字 其中xxx为关键字
docker rmi --force $(docker images | grep xxx | awk '{print $3}')
# 重启那些意外退出的容器
docker restart $(docker ps -a|grep Exited|awk '{print $1}')
常用软件启动
# 启动redis 以服务方式启动
docker run -d --name myredis -p 6379:6379 redis redis-server
# 和容器做交互-it 用redis-cli
docker exec -it 1dad7fd6ffd5 redis-cli
# rabbitmq
docker run -d --name myrabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:management
# mysql
docker run -d --name mymysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
# nginx 将前端代码映射到/usr/share/nginx/html
docker run -d --name myniginx -p 80:80 -v /frontcode:/usr/share/nginx/html nginx
# nginx 自定义配置
docker run \
-d \
-p 82:80 \
--restart=always \
-v ~/nginx/conf.d:/etc/nginx/conf.d \
-v ~/nginx/logs:/var/log/nginx \
nginx:1.21.6
# elk
docker pull sebp/elk
docker run -p 5601:5601 -p 9200:9200 -p 5044:5044 -e ES_MIN_MEM=128m -e ES_MAX_MEM=1024m -d --name elk sebp/elk
max_map_count问题以及解决
vim /etc/sysctl.conf
添加如下代码
vm.max_map_count=262144
-----
sysctl -p
3. 进入docker容器:
docker exec -it 容器ID /bin/bash
4. 修改配置文件
配置文件的位置:/etc/logstash/conf.d/02-beats-input.conf
将其中的内容都删掉,替换成下面的配置
input {
tcp {
port => 5044
codec => json_lines
}
}
output{
elasticsearch {
hosts => ["localhost:9200"]
}
}
5. 重启docker容器(大概等5-10分钟,等待服务重启)
docker restart elk
6. 访问Kibana
http://localhost:5601/
Dockerfile
Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。&& 符号连接命令,这样执行后,只会创建 1 层镜像.
vim Dockerfile
---------------
#注释
# FROM 定制的镜像都是基于 FROM 的镜像
FROM debian
# RUN:用于执行后面跟着的命令行命令
# shell 格式:RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。
# exec 格式 RUN ["可执行文件", "参数1", "参数2"]
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline
RUN echo 'build start'
RUN mkdir software
# 复制指令,从上下文目录中复制文件或者目录到容器里指定路径。
COPY aa /software
# ADD相比CPOY,压缩文件会自动复制并解压到容器里指定路径
ADD bb.tar.gz .
# VOLUME 将容器产生的数据挂到宿主机上
# 类似于 RUN 指令, CMD 在docker run 时运行 RUN 是在 docker build
# CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖
# 注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
CMD ["-c","ls -l"]
# 类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。
# 如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
# ENTRYPOINT ["<executeable>","<param1>","<param2>",...]
ENTRYPOINT ["/bin/sh"]
# 暴露一个端口
EXPOSE 8083
--------------------------
# 开始构建镜像 -t 指定一个名字 'name:tag' format
docker build -t demo .
docker run demo
# CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖
docker run demo -c date
docker compose
curl -L https://get.daocloud.io/docker/compose/releases/download/v2.2.3/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
离线导入导出
# 使用 docker export 命令根据容器 ID 将镜像导出成一个文件。
docker export f299f501774c > images.tar
# 导入镜像
docker import - new_hangger_server < images.tar
# 使用 docker save 命令根据容器 ID 将镜像保存成一个文件。 这个方法导入得镜像没有名字和标签
docker save 0fdf2b4c26d3 > images.tar
# 同时保存多个
docker save -o images.tar postgres:9.6 mongo:3.4
# 载入镜像
docker load < images.tar
两种方案的差别
- 两种方法不可混用。如果使用 import 导入 save 产生的文件,虽然导入不提示错误,但是启动容器时会提示失败,会出现类似"docker: Error response from daemon: Container command not found or does not exist"的错误。
export
导出的镜像文件体积小于save
保存的镜像docker import
可以为镜像指定新名称,docker load
不能对载入的镜像重命名export
不支持同时将多个镜像打包到一个文件中,save
可以export
导出是根据容器拿到的镜像,再导入时会丢失镜像所有的历史记录和元数据信息(即仅保存容器当时的快照状态),所以无法进行回滚操作。而save
保存的镜像,没有丢失镜像的历史,可以回滚到之前的层(layer)。docker export
的应用场景:主要用来制作基础镜像,比如我们从一个 ubuntu 镜像启动一个容器,然后安装一些软件和进行一些设置后,使用docker export
保存为一个基础镜像。然后,把这个镜像分发给其他人使用,比如作为基础的开发环境。docker save
的应用场景:如果我们的应用是使用docker-compose.yml
编排的多个镜像组合,但我们要部署的客户服务器并不能连外网。这时就可以使用docker save
将用到的镜像打个包,然后拷贝到客户服务器上使用docker load
载入。
离线安装Docker/Docker-Compose
https://download.docker.com/linux/static/stable/x86_64/
https://github.com/docker/compose/releases
- docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
# ARM国产服务器需要修改成65535
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
- install.sh
#!/bin/sh
# 安装docker
tar -xvf docker-20.10.14.tgz
cp docker/* /usr/bin/
cp docker.service /etc/systemd/system/
chmod +x /etc/systemd/system/docker.service
systemctl daemon-reload
systemctl start docker
cat <<EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
systemctl enable docker
systemctl daemon-reload
systemctl restart docker
docker -v
echo 'docker安装成功...'
cp docker-compose-linux-x86_64 /usr/bin/docker-compose
chmod +x /usr/bin/docker-compose
docker-compose -v
echo 'docker-compose安装成功...'
- uninstall.sh
#!/bin/sh
echo '删除docker.service...'
rm -f /etc/systemd/system/docker.service
echo '删除docker文件...'
rm -rf /usr/bin/docker*
echo '重新加载配置文件'
systemctl daemon-reload
echo '卸载成功...'
遇到的问题
- docker运行容器报错 WARNING: IPv4 forwarding is disabled. Networking will not work.
#在宿主机上执行
echo "net.ipv4.ip_forward=1" >>/usr/lib/sysctl.d/00-system.conf
#重启network和docker服务
systemctl restart network && systemctl restart docker
- 以root权限进入Docker容器
# 首先在启用Docker容器的时候,必须加上--privileged=true。例:
`docker run -d -p 8888:8888 --privileged=true xxx`
# 在进入容器时,使用:
docker exec -it -u root [ContainerID] /bin/bash
# 此时你已经以root身份进入docker容器了 ,就算使用su也不需要输入密码。
- 非root用户使用docker
# gitlab-runner用户添加到docker组
sudo usermod -aG docker gitlab-runner
library initialization failed - unable to allocate file descriptor table - out of memory
在一些比较老的机器或者是ARM内核的国产服务器上容易出现
(1) LimitNOFILE=infinity 虽然是不限制,但是在systemctl版本小于234的时候不生效,查看systemctl版本:systemctl --version
(2) docker容器的ulimit太小了,有文档说太大也不行
3.解决方法
#修改/lib/systemd/system/docker.service文件
LimitCORE=infinity
LimitNOFILE=infinity
LimitNPROC=infinity
改成
LimitCORE=65535
LimitNOFILE=65535
LimitNPROC=65535
#重启docker服务
docker -mysql 导入导出
# 查找mysql 容器ID
docker ps
# 进入mysql容器
docker exec -it 708927398ed3 bash
# 导出数据库 输入mysql密码
mysqldump -u root -p 123456 > dump.sql
# pwd 记住导出文件地址
pwd
# 退出容器
exit
# 把容器中dump.sql文件拷贝到本机
docker cp 708927398ed3:dump.sql ~/
# 把本地文件复制进容器
docker cp /home/change20231229.sql 容器ID:/change20231229.sql
# 进入mysql容器
docker exec -it 容器ID bash
#导入
mysql -u root -p123456 --default-character-set=utf8 dbname < change20231229.sql
快速打包脚本
#!/bin/bash
declare -A map
# 定义保存镜像的目录
save_dir="/vagrant/images"
# 确保保存目录存在
mkdir -p "$save_dir"
# 定义镜像数组
images=(
"xxx:202408131631"
)
# 拉取并保存每个镜像
for image in "${images[@]}"
do
# 去除前缀并替换冒号为下划线
filename=$(echo "$image" | sed 's/swr.cn-north-4.myhuaweicloud.com\/xiaoshou\///' | sed 's/:/-/g' | sed 's/$/.tar/')
save_path="${save_dir}/${filename}"
echo "Pulling and saving image: $image as $save_path"
# 拉取镜像
docker pull "$image"
# 保存镜像到tar文件
docker save "$image" -o "$save_path"
echo "Image saved as $save_path"
done
echo "All images have been pulled and saved."