Linux环境Docker安装与使用教程

VMware介绍

Docker是一个开源应用容器引擎,类似于虚拟机,Go语言编写。可以打包应用依赖到一个可移植的容器中。

可以利用 Docker 的方法来快速交付,测试和部署代码。

Centos Linux安装Docker

直接:

1
yum -y install docker-io

或者:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
yum install -y yum-utils device-mapper-persistent-data lvm2 # 安装依赖
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 配置源
yum list docker-ce --showduplicates | sort -r # 查看支持版本
yum install docker-ce-18.06.3.ce # 安装,默认安装目录/var/lib/docker
systemctl start docker # 启动
systemctl enable docker # 开机启动
docker version # 查看版本
docker ps # 查看当前正在运行的容器
docker start/stop id/name # 启动/停止某个容器
docker rm <the-container-id> # 移除容器
docker images # 查看本地镜像
docker ps -a # 查看所有包括停止的容器

curl -L https://get.daocloud.io/docker/compose/releases/download/1.26.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose #下载docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version

在编辑好的yml目录中执行启动关闭项目

1
2
docker-compose up
docker-compose down

镜像加速

1
2
3
4
5
6
7
8
9
10
11
12
https://cr.console.aliyun.com # 注册阿里云,选择镜像中心,镜像加速
会有使用说明:
针对Docker客户端版本大于 1.10.0 的用户
您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxxxxx.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

可以写一个脚本docker-install.sh,下面内容就够

1
2
3
4
5
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce-20.10.9
systemctl start docker
systemctl enable docker

卸载重新安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 卸载
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 查看仓库有哪些版本
yum list docker-ce --showduplicates | sort -r
# 安装新版本 sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
yum install docker-ce-20.10.2 docker-ce-cli-20.10.2 containerd.io
# 查看版本
docker -v
sudo systemctl start docker
# 下载官方getting started 编译
docker build -t getting-started .
# 启动
docker run -dp 80:80 getting-started
# curl访问或者浏览器访问
curl http://localhost

错误

ERROR: Couldn't connect to Docker daemon at http+docker://localhost - is it running
Docker未启动,执行命令:service docker start

ERROR: Failed to Setup IP tables: Unable to enable SKIP DNAT rule: (iptables failed: iptables --wait -t nat -I DOCKER -i br-3cf202aa8f9b -j RETURN: iptables: No chain/target/match by that name.
关闭防火墙需要重启docker,执行命令:service docker restart

tcp 47.107.215.73:443: i/o timeout
可能原因:网络不通,url地址拼写错误

Error parsing reference: "python:alpine AS base" is not a valid repository/tag: invalid reference format
版本兼容问题:升级docker版本

Exception caught: java.util.concurrent.ExecutionException: com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException: org.apache.http.conn.HttpHostConnectException: Connect to localhost:2375 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect -> [Help 1]
升级docker-maven-plugin到1.0.0版本。docker开启远程API端口

1
2
3
4
5
6
7
vi /etc/sysconfig/docker

other_args="-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock"

:wq

service docker restart

在windows系统环境变量中新建DOCKER_HOST值为tcp://{docker_ip}:2375,将这里的{docker_ip},替换为docker所在的centos服务器IP或主机名.

1
2
3
4
5
6
7
#vi /usr/lib/systemd/system/docker.service
# 在ExecStart这一行末尾加上参数 -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
# 重新加载配置
systemctl daemon-reload
# 启动docker
systemctl restart docker

解决 docker 报错: Error starting daemon: error initializing graphdriver: backing file system is unsupported for this graph driver
journalctl -xe 查询错误信息,dockerd 命令。
所以尝试修改 /etc/sysconfig/docker-storage 为:
DOCKER_STORAGE_OPTIONS=”–storage-driver btrfs “
systemctl start docker 重启解决问题

docker的安装目录

1
2
3
4
5
docker info | grep "Docker Root Dir"
# 或者在详情中查看我的是/var/lib/docker,/var/lib/docker是容器
docker info
# 查看占用空间 driver是overlay2
du -sh /var/lib/docker/overlay2 或者 du -sh * | sort -h

数据Volume

volumes:Docker管理宿主机文件系统的一部分,默认位于 /var/lib/docker/volumes 目录中。在Docker中,要想实现数据的持久化(所谓Docker的数据持久化即数据不随着Container的结束而结束),需要将数据从宿主机挂载到容器中。
目前Docker提供了三种不同的方式将数据从宿主机挂载到容器中:volumes,bind mounts,tmpfs(一般不用)

1
2
3
4
5
6
7
8
9
10
11
docker volume create test-nginx-vol # 创建
docker volume ls # 查看所有
docker volume inspect test-nginx-vol # 检查当个volume
docker run -d -it --name=test-nginx -p 8100:80 -v test-nginx-vol:/usr/share/nginx/html nginx # -v代表挂载数据卷,这里使用自定数据卷test-nginx-vol,并且将数据卷挂载到 /usr/share/nginx/html (这个目录是yum安装nginx的默认网页目录),-p 8100:80对外提供8100端口访问,网页访问http://localhost:8100
vi /var/lib/docker/volumes/test-nginx-vol/_data/index.html # 修改该html网页会直接变化或者进入容器
docker exec -it test-nginx /bin/bash # 进入容器
vi /usr/share/nginx/html/index.html # 一样可以修改网页,如果没有vim命令就需要安装

# docker中安装vim命令,直接执行apt-get install vim会出现Unable to locate package vim
apt-get update # 同步 /etc/apt/sources.list 和 /etc/apt/sources.list.d 中列出的源的索引
apt-get install vim

进入containers目录,每一个序列号,都是一个镜像

常用命令

docker ps 查看启动的容器
docker exec -it id(name) /bin/bash 进入容器,如果出错用把/bin/bash改成/bin/sh
docker rmi 镜像id 删除镜像

文件拷贝到容器与拷贝出容器

1
2
docker cp mysql:/home/test/abc.txt ./ # 拷贝出来
docker cp abc.txt mysql:/home/ # 拷贝进去

让容器执行命令

可以把脚本文件拷贝到容器,然后通过这个命令执行脚本

1
2
docker exec -it 容器名/容器ID bash # 进入容器执行
docker exec 容器名/容器ID 命令 # 容器外执行,docker exec mysql mkdir /home/abc

获取常用镜像并使用的例子

不对容器进行删除操作,数据也是不会丢失的。
-v做目录映射的时候要检查下宿主机目录下的文件是否正常,如果文件是有问题的会导致启动容器使用宿主机的错误文件启动,导致程序出错。
自己安装的mysql,如果对目录进行了映射,就得把安装好的正常的目录拷贝一个到宿主机中,否则启动会出错。
查看容器日志docker logs mysql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# 下载镜像
docker pull centos:7.6.1810
docker images

# 运行
docker run -d --name centos76 -h centos76 \ # -d 后台运行
-p 222:22 \
--privileged=true \
centos:7.6.1810 /usr/sbin/init # 需要执行个/usr/sbin/init命令才行 或者直接 init
docker exec -it centos76 bash

docker cp app-xxx.tar.gz centos76:root # 拷贝文件到Docker容器中

# --- 不一定需要配置 ---
#进入Linux容器
[root@wcbpg ~]# docker exec -it centos76 bash
# 下载基础源
[root@centos76 /]# curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2523 100 2523 0 0 22307 0 --:--:-- --:--:-- --:--:-- 22526
# 配置epel源
[root@centos76 /]# curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0
100 664 100 664 0 0 43 0 0:00:15 0:00:15 --:--:-- 157
[root@centos76 /]#
[root@centos76 /]# sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo
[root@centos76 /]# yum clean all
[root@centos76 /]# rpm --rebuilddb
# 退出容器
[root@centos76 /]# exit
exit
[root@wcbpg ~]# docker cp /usr/share/zoneinfo/Asia/Shanghai centos76:/etc/localtime
#进入Linux容器
[root@wcbpg ~]# docker exec -it centos76 bash
[root@centos76 /]# rm -f /etc/localtime
[root@centos76 /]# cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
[root@centos76 /]# timedatectl set-timezone "Asia/Shanghai"
# 配置容器内的SSH
[root@centos76 /]# yum install -y openssh-clients openssh-server initscripts net-tools
#在容器内安装其他依赖
[root@centos76 /]#yum install -y openssh-clients openssh-server initscripts net-tools


timedatectl | grep "Time zone" # 查看时区
# --- 不一定需要配置 ---


yum install tcp_wrappers-libs 或者 wget http://mirror.centos.org/centos/7/os/x86_64/Packages/tcp_wrappers-libs-7.6-77.el7.x86_64.rpm (libwrap.so.0()(64bit) is needed by vsftpd-3.0.2-25.el7.x86_64)
rpm -Uvh tcp_wrappers-libs-7.6-77.el7.x86_64.rpm
yum install logrotate(logrotate is needed by vsftpd-3.0.2-25.el7.x86_64)
yum install groff-base
yum -y install numactl (libnuma.so.1()(64bit) is needed by mysql-community-server-8.0.26-1.el7.x86_64)
yum install libedit
yum install systemd-sysv
yum install yum-cron (/etc/cron.d is needed by sysstat-10.1.5-19.el7.x86_64)
yum install openssl
yum install sudo
yum -y install iproute

## 汇总
yum install tcp_wrappers-libs logrotate groff-base numactl libedit systemd-sysv yum-cron openssl sudo iproute

# 安装应用程序
# 做好基础配置
# root增加sudo功能
echo "root ALL=(ALL:ALL) ALL" >> /etc/sudoers

制作镜像:
docker commit centos76 xxxx:1.0

倒出镜像:
docker export xxxx:1.0 > xxx_server.tar
导入镜像
docker import - new_xxx_server < xxx_server.tar # 横线也要有
docker import my_ubuntu_v3.tar runoob/ubuntu:v4
docker images # 查看镜像

save load 也行信息更完整: docker save xxxxx:1.0 > xxxx_server.tar

问题解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
error: Failed dependencies:
libwrap.so.0()(64bit) is needed by vsftpd-3.0.2-25.el7.x86_64
logrotate is needed by vsftpd-3.0.2-25.el7.x86_64
Failed to execute operation: No such file or directory
Failed to restart vsftpd.service: Unit not found.

error: Failed dependencies:
/usr/bin/perl is needed by mysql-community-server-8.0.26-1.el7.x86_64
libnuma.so.1()(64bit) is needed by mysql-community-server-8.0.26-1.el7.x86_64
libnuma.so.1(libnuma_1.1)(64bit) is needed by mysql-community-server-8.0.26-1.el7.x86_64
libnuma.so.1(libnuma_1.2)(64bit) is needed by mysql-community-server-8.0.26-1.el7.x86_64
perl(Getopt::Long) is needed by mysql-community-server-8.0.26-1.el7.x86_64
perl(strict) is needed by mysql-community-server-8.0.26-1.el7.x86_64

error: Failed dependencies:
groff-base is needed by perl-Pod-Perldoc-3.20-4.el7.noarch

Preparing... ########################################
package lrzsz-0.12.20-36.el7.x86_64 is already installed
error: Failed dependencies:
libedit.so.0()(64bit) is needed by ntp-4.2.6p5-29.el7.centos.2.x86_64
error: Failed dependencies:
/etc/cron.d is needed by sysstat-10.1.5-19.el7.x86_64
systemd-sysv is needed by sysstat-10.1.5-19.el7.x86_64

error: Failed dependencies:
make is needed by openssl-1:1.0.2k-25.el7_9.x86_64



docker安装MySQL

数据库不适合部署在docker中。

  1. 拉取官方镜像(使用5.7版本)
    1
    2
    docker pull mysql:5.7 # 拉取5.7版本,我们使用5.7版本,容器内目录/var/lib/mysql
    docker pull mysql # 拉取最新版本
  2. 查看镜像
    1
    sudo docker images
  3. 启动方式一,不建立目录映射
    1
    sudo docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
    • -name:容器名
    • -e:配置信息
    • -p:端口映射, 主机端口:容器端口
  4. 启动方式二,建立目录映射,制作安装脚本的时候映射的目录不要使用安装包的目录避免被误删
    1
    2
    3
    4
    5
    6
    sudo docker run -p 3306:3306 --name mysql \
    -v /usr/local/docker/mysql/conf:/etc/mysql \
    -v /usr/local/docker/mysql/logs:/var/log/mysql \
    -v /usr/local/docker/mysql/data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=root \
    -d mysql:5.7
    • -v: 主机目录:容器目录
  5. 查看docker进程
    1
    docker ps
  6. 重启mysql,删除容器,启动出错,重复启动用得上
    1
    2
    docker restart mysql
    docker rm ba7ef3e4ba975474b67c0f9126f07a4d88140e569323a77800aab8624361d67d # 谨慎使用会丢失容器数据
  7. 进入docker
    1
    2
    sudo docker exec -it mysql bash
    mysql -uroot -proot
  8. 查看或者设置外部访问权限
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    mysql>use mysql;
    mysql>grant all privileges on *.* to root@'%' identified by "root"; # 授权访问
    mysql>flush privileges;
    mysql>select host,user from user;
    +-----------+---------------+
    | host | user |
    +-----------+---------------+
    | % | root |
    | localhost | mysql.session |
    | localhost | mysql.sys |
    | localhost | root |
    +-----------+---------------+
    4 rows in set (0.00 sec)
  9. 通过win Navicat等工具尝试访问

问题

ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock’
可能是脚本语句按顺序执行,但是mysql服务还没完全初始化成功。所以可以sleep 10 休息10秒钟可能就可以连接上了。

docker安装redis

1
2
3
4
5
docker run -itd --name redis-test -p 6379:6379 redis # 第一次启动
docker start redis-test # 后续通过start/stop操作
docker ps
docker # 直接输入docker可以查看操作命令说明
docker inspect redis-test # 查看容器配置信息,可以查看data路径,bin路径

cli

1
2
3
4
5
6
7
8
9
10
11
12
13
redis-cli


select 0 # 选择数据库 默认是0
keys * # 查找匹配的key
get xxx # 查询指定key的value值
set test 1 # 设置
del test # 删除
exists test

sadd myset a # set操作
lpush list_test abc # list操作
lindex list_test 0 # 查询

docker安装ElasticSearch

问题修复

org.elasticsearch.indices.recovery.RecoveryFailedException...Recovery failed from...
简单修复:删除data目录与logs目录

java docker配置

  1. POM文件配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    <build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
    <execution>
    <goals>
    <goal>repackage</goal>
    </goals>
    </execution>
    </executions>
    </plugin>
    <!-- 跳过单元测试 -->
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
    <skipTests>true</skipTests>
    </configuration>
    </plugin>
    <plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>1.0.0</version>
    <configuration>
    <imageName>info-tech</imageName>
    <dockerDirectory>${project.basedir}</dockerDirectory><!--Dockerfile文件存放路径-->
    <resources>
    <resource>
    <targetPath>/</targetPath>
    <directory>${project.build.directory}</directory>
    <include>${project.build.finalName}.jar</include>
    </resource>
    </resources>
    </configuration>
    <!-- 运行命令 mvn clean package docker:build 打包并生成docker镜像 -->
    </plugin>
    </plugins>
    </build>
  2. 在工程创建Dockerfile,与pom文件同级
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    FROM java:8
    EXPOSE 8080

    VOLUME /tmp
    ADD info-tech.jar app.jar
    RUN bash -c 'touch /app.jar'
    ENTRYPOINT ["java","-jar","/app.jar"]
    # 参数说明
    # EXPOSE 指令用于指定容器将要监听的端口,需要配合 docker run -p PORT:EXPORT使用
    # RUN 每条RUN指定将在当前镜像基础上执行指定命令,并提交为新的镜像,通过&&可以把多条语句合并成一条
    # VOLUME 指定默认卷,会在volume目录下面生成随机码文件夹与之对应。然也可以指定/tmp 其效果都是在主机的/var/lib/docker/volumes目录下创建一个临时文件,并链接到容器的链接路径
    # ADD 相当于COPY文件到容器中,info-tech.jar是java工程包的名字不是镜像名字
    # ENTRYPOINT 启动的时候默认执行的命令
  3. 在开发环境增加环境变量DOCKER_HOST=tcp://localhost:2375 连接到目标Docker主机
  4. 开发环境执行mvn clean package docker:build打包到docker服务器
  5. 到docker服务器,启动
    1
    docker run -itd --name info-tech -p 8080:8080 info-tech:latest # --name 指定一个名称
  6. 制作成镜像分享
    1
    2
    3
    docker save -o info-tech.tar info-tech # 镜像打包输出到当前目录
    docker load < /xxx/xx/info-tech.tar # 上传到其他服务器,加载镜像
    docker images # 查看镜像、之后后面可以允许镜像

IDEA打包就行执行最上级工程中的→Lifecycle→package或者install。POM文件需要增加下面的maven插件配置。
还可以java打包成jar包上传至Docker服务器,在Docker服务器创建Dockerfile编写类似上面的脚本。执行 docker build -t info-tech . 然后运行容器docker run -d --name info-tech -p 8083:8083 info-tech

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

如果启动失败docker run -it info-tech可以看到错误信息
docker rm -f container-id强制移除进程 docker rmi image-id
docker内不能通过127.0.0.1访问主机的其他服务

根据容器名称启动之前启动过的容器 docker start info-tech 启动的容器可以统一命名成增加-run后缀比如info-tech-run

docker安装postgres

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
docker run \
-d \
--name postgres \
-p 5432:5432 \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres123456 \
-v ~/docker_data/pgsql/data:/var/lib/postgresql/data \
postgres:11


docker exec -it postgres /bin/bash
psql -U postgres
create database test;

\c test # 切换数据库

SELECT tablename FROM pg_tables
WHERE tablename NOT LIKE 'pg%'
AND tablename NOT LIKE 'sql_%'
ORDER BY tablename; # 查询数据库表

\d alarm # 查看alarm表的表结构

docker安装vsftpd

1
2
3
4
5
6
7
8
9
10
11
12
13
docker pull fauria/vsftpd

docker run -d -v /my/data/directory:/home/vsftpd \
-p 20:20 -p 21:21 -p 21100-21110:21100-21110 \
-e FTP_USER=myuser -e FTP_PASS=mypass \
-e PASV_ADDRESS=127.0.0.1 -e PASV_MIN_PORT=21100 -e PASV_MAX_PORT=21110 \
--name vsftpd --restart=always fauria/vsftpd # 开启主动与被动,PASV_ADDRESS:宿主机 ip,当需要使用被动模式时必须设置,--restart always 容器可以随docker服务启动而启动,如果外网用要用外网IP

# 测试
ftp 127.0.0.1
passive # 关闭或者开启被动模式,解决227 Entering Passive Mode (xxx,xxx,,xxx,xxx,x)问题,可能是Passive IP地址没设置对,防火墙也可以检查下是否端口都放开了

# 映射后的目录,就算是在主机上用root账号在/data/directory创建的文件,也是可以通过ftp账号进行删除的不会出现权限问题

进入容器添加账号的脚本,执行脚本的方法:

1
2
3
4
5
6
7
8
#docker exec -i -t vsftpd bash
#mkdir /home/vsftpd/test1
#echo -e "test1\nTtest111" >> /etc/vsftpd/virtual_users.txt
#/usr/bin/db_load -T -t hash -f /etc/vsftpd/virtual_users.txt /etc/vsftpd/virtual_users.db
#exit
#docker exec vsftpd mkdir /home/vsftpd/test1 # 执行后面db_load会自动创建
docker exec vsftpd bash -c "echo -e 'test1\nTest111' >> /etc/vsftpd/virtual_users.txt"
docker exec vsftpd /usr/bin/db_load -T -t hash -f /etc/vsftpd/virtual_users.txt /etc/vsftpd/virtual_users.db

海外阿里云上传,如果使用XShell的XFTP是走加密的上传速度是289KB/s,后面安装Docker FTP是420KB/s,之后再用SFTP结果速度也提高到了420KB/s 使用加密的SFTP容易断线。有点奇怪,当然没加密肯定是会快一些的,速度非常低的时候提现不出来。

docker安装nginx

建立nginx-install.sh

1
2
3
docker pull nginx
docker run --name nginx -p 8290:8290 -v /root/docker-install/nginx.conf:/etc/nginx/nginx.conf -v /home/docker-nginx/log:/var/log/nginx -v /home/test/files:/home/test/files -d nginx # 例子,映射配置文件
docker run --name nginx -p 8290:80 -v /home/docker-nginx/log:/var/log/nginx -v /home/test/files:/usr/share/nginx/html -d nginx # 例子,使用默认配置

docker安装redis

建立redis-install.sh

1
2
docker pull redis:latest
docker run -p 16379:6379 --name redis -v /docker/redis/data:/data -d redis --requirepass Test_55F --appendonly yes

docker安装mysql

建立mysql-install.sh

1
2
3
4
5
6
7
8
9
docker pull mysql:8.0
docker run --name mysql -p 33068:3306 -v /home/mysql/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=Test_123FFS! -e MYSQL_DATABASE=test -e MYSQL_USER=test -e MYSQL_PASSWORD=test_ss3dF! -d mysql:8.0 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --character_set_client=utf8mb3

docker run --name mysql -p 33068:3306 -v /home/mysql/datadir:/var/lib/mysql -v /root/docker-install/mysql:/docker-entrypoint-initdb.d -e MYSQL_ROOT_PASSWORD=Test_123FFS! -e MYSQL_DATABASE=test -e MYSQL_USER=test -e MYSQL_PASSWORD=test_ss3dF! -d mysql:8.0 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci # initdb.d 初始化脚本初始化数据库

docker run --name mysql -p 33068:3306 -v /root/docker-install/mysql-conf:/etc/mysql/conf.d -v /home/mysql/datadir:/var/lib/mysql -v /root/docker-install/mysql:/docker-entrypoint-initdb.d -e MYSQL_ROOT_PASSWORD=Test_123FFS! -e MYSQL_DATABASE=test -e MYSQL_USER=test -e MYSQL_PASSWORD=test_ss3dF! -d mysql:8.0

docker exec -i mysql sh -c 'exec mysql -uroot -pTest_123FFS!' < init.sql # 创建用户,数据库等
docker exec -i mysql sh -c 'exec mysql -uroot -pTest_123FFS! test' < test.sql # 导入方式

Docker制作镜像

正常用法是一个docker一个前端进程。

创建Dockerfile 内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
FROM centos:7

MAINTAINER Infotech
LABEL Description="test Docker image based on Centos 7."\
Version="1.0"

#RUN yum -y update && yum clean all

ADD jdk-8u202-linux-x64.tar.gz /usr/java

ENV JAVA_HOME /usr/java/jdk1.8.0_202
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $PATH:$JAVA_HOME/bin

ADD tomcat.tar.gz /home/test/
RUN mv /home/test/tomcat /home/test/tomcat-test1
RUN cp /home/test/tomcat-test1 /home/test/tomcat-test2 -r

#ADD tomcat.tar.gz /home/test/tomcat-test2

EXPOSE 8891
EXPOSE 8892

CMD /home/test/tomcat-test1/bin/startup.sh && tail -F /home/test/tomcat-test1/logs/catalina.out

执行docker build -t tomcat3 . 制作镜像
执行docker run --name tomcat3 -d tomcat3 启动

制作后台启动多个服务:
创建start.sh。 使用systemctl用不了,无法自动启动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash

#systemctl start tomcat-test1 #需要特权,而且没办法自启动启动
#systemctl start tomcat-test2 #需要特权,而且没办法自启动启动

# 启动脚本可以读取参数修改配置文件,对于yml文件可以使用python脚本进行修改
echo "$MYSQL_HOST" >> a.txt # 写日志

if [ "$MYSQL_PORT" != "**String**" ]; then
sed -i "s#3306#$MYSQL_PORT#g" /home/test/tomcat1/webapps/test/WEB-INF/classes/application-prod.yml
fi

python3 /changeconfig.py $REDIS_HOST $REDIS_PORT

/home/test/tomcat1/bin/startup.sh
/home/test/tomcat2/bin/startup.sh
tail -F /home/test/test1/logs/catalina.out

创建tomcat-test1.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[Unit]
Description=tomcat-test1
After=syslog.target network.target

[Service]
Type=forking
LimitCORE=infinity
LimitNOFILE=100000
LimitNPROC=100000
WorkingDirectory=/home/test/tomcat-test1
ExecStart=/home/test/tomcat-test1/bin/startup.sh
ExecStop=/home/test/tomcat-test1/bin/shutdown.sh
ExecReload=/bin/kill -s HUP $MAINPID
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

创建Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
FROM centos:7

MAINTAINER Infotech
LABEL Description="test Docker image based on Centos 7."\
Version="1.0"

#RUN yum -y update && yum clean all
RUN yum install -y unzip
RUN yum install -y python3

ADD jdk-8u202-linux-x64.tar.gz /usr/java
ADD start.sh /home
RUN chmod +x /home/start.sh
#ADD tomcat-test1.service /etc/systemd/system/
#ADD tomcat-test2.service /etc/systemd/system/

ADD PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl /
ADD changeconfig.py /


ENV JAVA_HOME /usr/java/jdk1.8.0_202
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $PATH:$JAVA_HOME/bin

ENV REDIS_HOST **String** #ENV REDIS_HOST = **String** 错误写法
ENV REDIS_PORT **String**

ADD tomcat.tar.gz /home/test/
RUN mv /home/test/tomcat /home/test/tomcat-test1
RUN cp /home/test/tomcat-test1 /home/test/tomcat-test2 -r

RUN pip3 install /PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl

ADD test1.war /home/test/tomcat-test1/webapps
ADD test2.war /home/test/tomcat-test2/webapps
RUN unzip -o /home/test/tomcat-test1/webapps/test1.war -d /home/test/tomcat-test1/webapps/test1 # 必须通过命令解压不然后面脚本报错 No such file or directory
RUN unzip -o /home/test/tomcat-test2/webapps/test2.war -d /home/test/tomcat-test2/webapps/test2 # 必须通过命令解压不然后面脚本报错 No such file or directory
RUN rm -rf /home/test/tomcat-test1/webapps/test1/test1.war

EXPOSE 8891
EXPOSE 8892

# CMD systemctl start tomcat-test1
# CMD /home/start.sh
CMD nohup sh -c '/home/test/tomcat-test1/bin/startup.sh && /home/test/tomcat-test2/bin/startup.sh && tail -F /home/test/tomcat-test1/logs/catalina.out' # 通过拼接实现调用多个程序,也可以写一个脚本调用多个start.sh,就是需要tail -F 避免docker进程退出

systemctl认不到环境变量,tomcat中的setclass.sh头部需要添加,可以ADD进去或者tomcat压缩包直接改好,或者通过命令修改文件,或者给好后ADD进去:
export JAVA_HOME=/usr/java/jdk1.8.0_202
export JRE_HOME=/usr/java/jdk1.8.0_202/jre

启动:
使用
docker run --name tomcat3 --privileged=true -d tomcat3
docker run --name tomcat3 --privileged=true -d tomcat3 /usr/sbin/init 使用/usr/sbin/init会导致无法自动调用启动脚本执行启动命令,支持在内部使用systemctl启动程序。

升级,可以通过脚本直接替换完整镜像。对于数据库升级可以读取docker中当前使用的镜像版本号与目标版本进行执行增量脚本,也可以人工一个个执行。

网络

默认桥接模式,启动的时候通过在宿主机上,可以通过iptables -t nat -L -n,查到一条DNAT规则:
DNAT tcp – 0.0.0.0/0 0.0.0.0/0 tcp dpt:8083 to:172.17.0.5:8083

打包

可以通过脚本从公网下载镜像包,进行运行
也可以直接制作好可以执行的镜像包运行
也可以镜像包加外部配置文件映射组合
可以基础组件与程序分离,也可以AllInOne

通过python修改配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import yaml
import sys
import codecs

redis_host=sys.argv[1]
redis_port=sys.argv[2]

with codecs.open("/home/test/tomcat-test1/webapps/test1/WEB-INF/classes/application-prod.yml",'r','UTF-8') as f:
result = f.read()
x=yaml.load(result,Loader=yaml.FullLoader)
print("history redis host:"+x["spring"]["redis"]["host"])
print("redis host:"+redis_host)
print("redis port:"+redis_port)

if redis_host!="**String**":
x["spring"]["redis"]["host"]=str(redis_host)
if redis_port!="**String**":
x["spring"]["redis"]["port"]=int(redis_port)
with open("/home/test/tomcat-test1/webapps/test1/WEB-INF/classes/application-prod.yml",'w') as w_f:
yaml.dump(x,w_f)

其他

查看docker占用内存

命令docker stats ,docker ps -a找到容器id ps -ef|grep 容器id找到进程id top -p 进程id,或者cat /proc/pid/status 里面的VmRSS

问题

用户使用docker ps 权限问题

执行sudo chmod a+rw /var/run/docker.sock命令

最容易出现的问题就是忘记关防火墙或者开放端口

【docker】iptables failed: iptables –wait -t nat -A DOCKER -p tcp -d 0/0 –dport 8888 -j DNAT –to-d

解决方法:systemctl restart docker

standard_init_linux.go:228: exec user process caused: exec format error

OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec format error: unknown

sh文件第一行加入 #!/bin/bash

执行脚本以后哪几种

有第一次启动才执行的初始化脚本。
有每次启动都执行的启动脚本。 如果restart每次都会调用修改配置的脚本,那么脚本就不能用替换的方法(第二次重启的时候实际上第一次已经替换过了,当然替换过来也会导致第二次替换不成功,实际可能也不会出什么问题,还是得比较慎重),就应该直接用yml写入的方法实现。重启想换参数,如果是用替换模式,由于已经被替换一次也会出现下一次无法被替换的情况。当然考虑需要修改配置参数进行重启的情况也比较少,可以根据具体情况考虑是否需要换种修改配置的模式。

后台运行

Docker的设计理念是在容器里面不运行后台服务,容器本身就是宿主机上的一个独立的主进程,也可以间接的理解为就是容器里运行服务的应用进程。一个容器的生命周期是围绕这个主进程存在的,所以正确的使用容器方法是将里面的服务运行在前台
当然可以run命令增加权限支持后台运行:--privileged=true /usr/sbin/init
例子:docker run --name tomcat3 --privileged=true -d tomcat3 /usr/sbin/init,docker run -d -it --privileged nginx-1 /usr/sbin/init

启动失败

制作的镜像启动失败,通过命令查看启动失败日志
docker logs tomcat

实战需要考虑的

制作一键容器制作脚本
制作一键容器启动脚本
制作升级脚本

对于应用升级一般直接替换Docker镜像

简单应用:

  1. 简单使用就是安装Docker程序,Docker里面程序使用我们正常程序的一键安装包来安装,把权限与缺少的依赖补上运行使用systemctl
  2. 然后把需要对外的端口expose出来
  3. 然后把数据、配置、日志等目录映射到主机
  4. 制作一个Dockerfile脚本与维护手册
  5. 好处是程序安装脚本实体机与Docker可以共用
  6. 程序需要升级也是进入docker执行升级脚本(这样程序也得映射出来,可以把/home/xxx 或者/usr/local等程序目录直接映射到本机,当然也可以通过命令保存所做的更改) 好处是一个镜像可以无限升级使用,或者用新docker镜像替代旧Docker镜像,然后执行增量脚本,如果用镜像模式对于数据库还得做判断当前是哪个版本需要执行哪些脚本。
  7. 不一定都用自动化脚本,也可以通过教程的方式,通过命令来构建工程镜像运行

比较复杂的就是各个应用程序单独一个镜像,维护成本比较高,各自有各自的优缺点。

总结

ftp与使用ftp里面文件的应用可以使用不同的容器,然后都-v映射到主机上同一个目录下面,应用容器使用Apache提供的目录文件变化监听器来监听修改移动文件。是可行的。

参考