Docker Compose 启动顺序#
docker compose可以同时部署多个服务,但是有时候服务是相互依赖的,比如你的web service需要依赖mysql,所以只有当mysql 服务启动好之后才能启动你的web service,此时我们就需要控制docker compose 配置文件中服务的启动顺序。
创建项目#
创建项目,这里使用spring-boot创建一个mysql的读写应用,该应用依赖mysql服务,所以我们的应用包括两个部分
一个是后台服务由spring boot 编写,另外一个是mysql提供数据库服务。具体spring boot mysql
目录结构如下: 奇技淫巧 find . -maxdepth 2 | sed -e "s/[^-][^\/]*\// |/g" -e "s/|\([^ ]\)/|-\1/"
|-docker //构建docker依赖的文件夹
| |-init_db.sql //为了延长数据库启动时间,我们在启动时执行创建脚本
| |-wait.sh //延时脚本,等待mysql启动
|-mvnw.cmd
|-Dockerfile //Dockerfile 编译web service的配置文件
|-pom.xml
|-docker-compose.yml //docker compose配置文件
|-src
| |-test
| |-main
编写shell 脚本#
shell 脚本循环ping mysql 服务端口,直到mysql 启动,然后启动web服务
#!/bin/bash
echo "Waiting for mysql"
echo "$DB_HOST"
echo "$DB_PORT"
until nc -z -v -w30 $DB_HOST $DB_PORT
do
echo "Waiting for database connection..."
sleep 3
done
echo -e "\nmysql ready\n"
echo -e "------------------start ngo------------------"
java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar ngo.jar
echo -e "------------------ngo ready------------------"
编写Dockerfile#
Dockerfile 用来将我们的应用编译成image, 然后通过把image部署到容器中向外提供服务,与之前不同的是我们通过
shell 脚本来启动服务
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAVA_OPTS
ENV JAVA_OPTS=$JAVA_OPTS
COPY ./target/ngo-0.0.1-SNAPSHOT.jar ngo.jar
ADD ./docker/wait.sh wait.sh
CMD ["chmod", "+x", "wait.sh"]
ENTRYPOINT ["sh", "wait.sh"]
编写docker-compose#
docker-compose.yml文件中定义了两个服务spring-boot-gs-data, 以及db. 这里有两种方式, 一是在容器内,二是通过docker-machin。与之前不同的是我们在这里将本地的初始化脚本copy到mysql container中的/docker-entrypoint-initdb.d目录,mysql启动时会使用此目录下的脚本初始化数据库
version: '3.3'
services:
db:
image: mysql
container_name: mysql-container
volumes:
- ./docker/init_db.sql:/docker-entrypoint-initdb.d/init_db.sql
environment:
- MYSQL_USER=springuser
- MYSQL_PASSWORD=ThePassword
- MYSQL_DATABASE=db_example
- MYSQL_ROOT_PASSWORD=root
gs_data:
build: .
image: spring-boot-gs-data
container_name: gs-data-container
ports:
- "8080:8080"
depends_on:
- db
environment:
- DB_HOST=db
- DB_PORT=3306
- DB_USER=springuser
- DB_PASSWORD=ThePassword
- DB_NAME=db_example
运行#
启动时只需要执行如下命令即可一次性部署db,和gs_data两个服务,具体是否还需要其他服务,可以依赖你的需求定制
docker-compose.yml
docker-compose up //前台启动,启动时会在命令行打印相关的日志信息
docker-compose up -d //后台启动
输出
docker-compose up
Building ngo //编译NGO service
Step 1/8 : FROM openjdk:8-jdk-alpine
---> 97bc1352afde
Step 2/8 : VOLUME /tmp
---> Using cache
---> 6d58c198c55c
Step 3/8 : ARG JAVA_OPTS
---> Using cache
---> c3d1f12e9b40
Step 4/8 : ENV JAVA_OPTS=$JAVA_OPTS
---> Using cache
---> 0a9e45fe483a
Step 5/8 : COPY ./target/ngo-0.0.1-SNAPSHOT.jar ngo.jar
---> 08215ddc23c1
Step 6/8 : ADD ./docker/wait.sh wait.sh
---> 703a04395914
Step 7/8 : CMD ["chmod", "+x", "wait.sh"]
---> Running in 11499b449975
Removing intermediate container 11499b449975
---> 4caa2d7dd8f2
Step 8/8 : ENTRYPOINT ["sh", "wait.sh"] //通过脚本来启动ngo 服务
---> Running in 42a5932ef9a2
Removing intermediate container 42a5932ef9a2
---> ffaf53498be9
Successfully built ffaf53498be9
Successfully tagged ngo:latest
WARNING: Image for service ngo was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating mysql-container ... done
Creating server_ngo_1 ... done
Attaching to mysql-container, server_ngo_1
mysql-container | Initializing database
ngo_1 | Waiting for mysql
ngo_1 | db
ngo_1 | 3306
ngo_1 | Waiting for database connection... //在数据库未启动时,会持续等待并打印此句
ngo_1 | db (172.18.0.2:3306) open
ngo_1 |
ngo_1 | mysql ready //数据库初始化完毕,启动ngo 服务
ngo_1 |
mysql-container | 2018-12-15T18:58:31.516026Z 0 [Note] mysqld: ready for connections.
mysql-container | Version: '5.7.24' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
ngo_1 | ------------------start ngo------------------
ngo_1 |
查看运行的container
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0ceb404fed0a ngo "sh wait.sh chmod +x…" 21 minutes ago Up 1 second 0.0.0.0:8080->8080/tcp server_ngo_1
03a8a8cdf73d mysql:5.7 "docker-entrypoint.s…" 21 minutes ago Up 3 seconds
删除container, 删除镜像使用docker rm 容器名 即可,容器名可以通过docker ps查询
docker rm 0ceb404fed0a
删除镜像, 删除镜像之前保证没有container使用该镜像,如果有需要先删除container
docker image rm ngo
查看ngo container, 通过Dockefile我们把宿主机上的jar文件以及shell 脚本copy到了ngo container中,
docker exec -it 0ceb404fed0a ls -al
total 53248
drwxr-xr-x 1 root root 4096 Dec 15 18:58 .
drwxr-xr-x 1 root root 4096 Dec 15 18:58 ..
-rwxr-xr-x 1 root root 0 Dec 15 18:58 .dockerenv
drwxr-xr-x 2 root root 4096 Sep 11 20:23 bin
drwxr-xr-x 5 root root 340 Dec 15 19:19 dev
drwxr-xr-x 1 root root 4096 Dec 15 18:58 etc
drwxr-xr-x 2 root root 4096 Sep 11 20:23 home
drwxr-xr-x 1 root root 4096 Oct 24 22:31 lib
drwxr-xr-x 5 root root 4096 Sep 11 20:23 media
drwxr-xr-x 2 root root 4096 Sep 11 20:23 mnt
-rw-r--r-- 1 root root 54456491 Dec 15 18:53 ngo.jar
dr-xr-xr-x 136 root root 0 Dec 15 19:19 proc
drwx------ 2 root root 4096 Sep 11 20:23 root
drwxr-xr-x 2 root root 4096 Sep 11 20:23 run
drwxr-xr-x 2 root root 4096 Sep 11 20:23 sbin
drwxr-xr-x 2 root root 4096 Sep 11 20:23 srv
dr-xr-xr-x 13 root root 0 Dec 15 19:19 sys
drwxrwxrwt 5 root root 4096 Dec 15 18:58 tmp
drwxr-xr-x 1 root root 4096 Oct 24 22:31 usr
drwxr-xr-x 1 root root 4096 Sep 11 20:23 var
-rw-r--r-- 1 root root 465 Dec 14 16:34 wait.sh
查看mysql container, 它是通过docker compose 自动部署的,
docker exec -it 03a8a8cdf73d bash
ls -al
total 80
drwxr-xr-x 1 root root 4096 Dec 15 18:58 .
drwxr-xr-x 1 root root 4096 Dec 15 18:58 ..
-rwxr-xr-x 1 root root 0 Dec 15 18:58 .dockerenv
drwxr-xr-x 1 root root 4096 Nov 16 01:14 bin
drwxr-xr-x 2 root root 4096 Oct 20 10:40 boot
drwxr-xr-x 5 root root 340 Dec 15 19:19 dev
drwxr-xr-x 1 root root 4096 Dec 15 18:58 docker-entrypoint-initdb.d
lrwxrwxrwx 1 root root 34 Nov 16 01:14 entrypoint.sh -> usr/local/bin/docker-entrypoint.sh
drwxr-xr-x 1 root root 4096 Dec 15 18:58 etc
drwxr-xr-x 2 root root 4096 Oct 20 10:40 home
drwxr-xr-x 1 root root 4096 Nov 12 00:00 lib
drwxr-xr-x 2 root root 4096 Nov 12 00:00 lib64
drwxr-xr-x 2 root root 4096 Nov 12 00:00 media
drwxr-xr-x 2 root root 4096 Nov 12 00:00 mnt
drwxr-xr-x 2 root root 4096 Nov 12 00:00 opt
dr-xr-xr-x 136 root root 0 Dec 15 19:19 proc
drwx------ 1 root root 4096 Nov 16 01:11 root
drwxr-xr-x 1 root root 4096 Nov 16 01:14 run
drwxr-xr-x 2 root root 4096 Nov 12 00:00 sbin
drwxr-xr-x 2 root root 4096 Nov 12 00:00 srv
dr-xr-xr-x 13 root root 0 Dec 15 19:19 sys
drwxrwxrwt 1 root root 4096 Dec 15 19:19 tmp
drwxr-xr-x 1 root root 4096 Nov 12 00:00 usr
drwxr-xr-x 1 root root 4096 Nov 12 00:00 var
//当我们查看docker-entrypoint-initdb.d目录时会发现我们数据库的初始化脚本
//数据库启动的时候会执行此脚本
cd docker-entrypoint-initdb.d/
root@03a8a8cdf73d:/docker-entrypoint-initdb.d# ls
init_db.sql