Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | 51CTO学院 | CSDN程序员研修院 | OSChina 博客 | 腾讯云社区 | 阿里云栖社区 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏多维度架构

1.13. Docker Example

1.13.1. registry

		
docker run -d -p 5000:5000 --name registry registry:latest
		
		

1.13.1.1. Auth + SSL

			
iMac:registry neo$ mkdir etc			
iMac:registry neo$ htpasswd -Bbn neo chen > etc/htpasswd

or
	
docker run --entrypoint htpasswd registry:2 -Bbn neo passw0rd > etc/htpasswd			
			
			

			
	
			
			
			
docker run -d \
  --restart=always \
  --name registry \
  -v `pwd`/etc:/usr/local/etc \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/usr/local/etc/htpasswd \
  -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/usr/local/etc/domain.cer \
  -e REGISTRY_HTTP_TLS_KEY=/usr/local/etc/domaon.key \
  -p 443:443 \
  registry:2			
			
			

1.13.2. Example Java - Spring boot with Docker

1.13.2.1. 获取 CentOS 7 镜像

docker pull centos:7

		
# docker pull centos:7
7: Pulling from library/centos
343b09361036: Pull complete 
Digest: sha256:bba1de7c9d900a898e3cadbae040dfe8a633c06bc104a0df76ae24483e03c077
Status: Downloaded newer image for centos:7
		
		

基于 CentOS 7 运行一个容器

docker run -it --name mycentos docker.io/centos:7 /bin/bash

		
# docker run -it --name mycentos docker.io/centos:7 /bin/bash
		
		

运行后直接进入了容器的shell控制台默认是bash

1.13.2.2. 安装 openjdk

		
# yum install -y java-1.8.0-openjdk

# cat >> /etc/profile.d/java.sh <<'EOF'
export JAVA_HOME=/usr/java/default
export JAVA_OPTS="-server -Xms2048m -Xmx4096m -Djava.io.tmpdir=/tmp -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF8 -Duser.timezone=GMT+08"
export CLASSPATH=$JAVA_HOME/lib:$JAVA_HOME/jre/lib:.
export PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin:
EOF

# source /etc/profile.d/java.sh
		
		

检查Java是否安装成功

		
# whereis java
java: /usr/bin/java /usr/lib/java /etc/java /usr/share/java /usr/share/man/man1/java.1.gz

# java -version
openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-b11)
OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode)
		
		

创建应用程序目录

# mkdir -p /www/netkiller.cn/www.netkiller.cn/		
		

推出当前容器

# exit
		

1.13.2.3. Spring boot 包

复制 jar 文件到Docker容器

		
docker cp /www/netkiller.cn/www.netkiller.cn/www.netkiller.cn-0.0.1.war mycentos:/usr/local/libexec
		
		

1.13.2.4. 启动 Spring boot 项目

启动容器

		
# docker start mycentos
mycentos		
		
		

进入容器

		
# docker exec -it mycentos /bin/bash
		
		

如果仅仅是测试可以手动启动 Srping boot 项目

		
# cat >> /root/run.sh <<EOF
java -server -Xms2048m -Xmx8192m -jar /usr/local/libexec/www.netkiller.cn-0.0.1.war
EOF

chmod u+x /root/run.sh
		
		

生产环境请使用启动脚本

				
# curl -s https://raw.githubusercontent.com/oscm/build/master/Application/Spring/service/springbootd -o /etc/init.d/springbootd
# chmod +x /etc/init.d/springbootd
		
		

编辑启动脚本 /etc/init.d/springbootd 修改下面配置项

		
##############################################
BASEDIR="/www/netkiller.cn/api.netkiller.cn"
JAVA_HOME=/srv/java
JAVA_OPTS="-server -Xms2048m -Xmx8192m -Djava.security.egd=file:/dev/./urandom"
PACKAGE="api.netkiller.cn-0.0.2-release.jar"
CONFIG="--spring.config.location=$BASEDIR/application.properties -Dspring.profiles.active=production -Dserver.port=8080 -Dlog.level=info"
USER=www
##############################################
NAME=springbootd
PROG="$JAVA_HOME/bin/java $JAVA_OPTS -jar $BASEDIR/$PACKAGE $CONFIG"
LOGFILE=/var/tmp/$NAME.log
PIDFILE=/var/tmp/$NAME.pid
ACCESS_LOG=/var/tmp/$NAME.access.log
##############################################
		
		

你也可以使用 systemd 启动脚本,详见《Netkiller Java 手札》

1.13.2.5. 基于 CentOS 7 制作 spring 镜像

docker commit mycentos springboot:1

		
# docker commit mycentos springboot:1
sha256:757d92d642d1b5a7b244f6ddf89f24a8d463d154438651c83ba51a644b401782		
		
		

启动 spring boot 容器

		
# docker run -d --name springboot -p 80:8080 springboot:1 /root/run.sh
		
		

		
-d: 以守护进程方式启动 
--name:指定容器的名称 
-p:映射容器8080端口到宿主机的80端口 
springboot:1 :上一步制作好的springboot镜像,版本号为1	
		
		

启动容器

		
# docker start springboot		
		
		

停止容器

		
# docker stop springboot		
		
		

1.13.3. Redis

http://download.redis.io/redis-stable/redis.conf

http://download.redis.io/redis-stable/sentinel.conf

1.13.3.1. Docker 命令

获取 Redis 镜像

docker pull redis

		
# docker pull redis  
Using default tag: latest
latest: Pulling from library/redis
10a267c67f42: Pull complete 
5b690bc4eaa6: Pull complete 
4cdd94354d2a: Pull complete 
71c1f30d820f: Pull complete 
c54584150374: Pull complete 
d1f9221193a6: Pull complete 
d45bc46b48e4: Pull complete 
Digest: sha256:548a75066f3f280eb017a6ccda34c561ccf4f25459ef8e36d6ea582b6af1decf
Status: Downloaded newer image for redis:latest
		
			
启动一个 Redis 实例
			
# docker run --name my-redis -d redis
10207174e18f61290f9c869e6437fa787e459e07b076b82cedf800a8c37c515d
			
			

查看启动情况

		
# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
10207174e18f        redis               "docker-entrypoint..."   8 minutes ago       Up 8 minutes        6379/tcp            my-redis
		
			
进入 Redis
		
# docker run -it --link my-redis:redis --rm redis redis-cli -h redis -p 6379
redis:6379> set name neo
OK
redis:6379> get name
"neo"
redis:6379> exit
		
			
启动一个 Redis 实例并映射 6379 端口
		
# docker stop my-redis
my-redis		
		
# docker rm my-redis
my-redis

# docker run --name my-redis -d -p 6379:6379 redis
10207174e18f61290f9c869e6437fa787e459e07b076b82cedf800a8c37c515d

# docker ps -a                                    
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
1c4540d8617f        redis               "docker-entrypoint..."   2 seconds ago       Up 1 second         0.0.0.0:6379->6379/tcp   my-redis
		
			

检查端口

		
# ss -lnt | grep 6379
LISTEN     0      128         :::6379                    :::*  
		
			
维护容器

使用下面命令进入容器维护 Redis

		
# docker exec -it my-redis /bin/bash
root@1c4540d8617f:/data#

root@1c4540d8617f:/data# redis-server -v
Redis server v=3.2.9 sha=00000000:0 malloc=jemalloc-4.0.3 bits=64 build=a30533b464d1689b
		
			

1.13.3.2. Docker compose

		
version: "3.7"
services:
  redis:
    image: redis:latest
    container_name: redis
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/var/lib/redis
    restart: always
    networks:
      - dev

networks:
  dev:
    driver: bridge

volumes:
  redis_data:
		
		

		
version: '3.9'

services:
  redis:
    image: redis:alpine
    container_name: redis
    restart: always
    hostname: redis.netkiller.cn
    user: redis:redis
    privileged: true
    environment:
      - TZ=Asia/Shanghai
      - LANG=en_US.UTF-8
    ports:
      - 6379:6379
    volumes:
      - ./conf/redis.conf:/etc/redis.conf
      - redis:/var/lib/redis
      - ./logs:/var/log/redis
    entrypoint: redis-server /etc/redis.conf
    command: 
      --requirepass passw0rd
volumes:
  redis:
		
		

确认配置生效

		
neo@MacBook-Pro-Neo ~ % docker exec -it redis redis-cli -a passw0rd                 
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> config get dir
1) "dir"
2) "/var/lib/redis"
127.0.0.1:6379> 		
		
		

1.13.3.3. Docker Stack

		
version: '3.8'

services:
  redis:
    image: redis:latest
    environment:
      - TZ=Asia/Shanghai
    hostname: redis
    ports:
      - 6379:6379
    networks:
      - test
    volumes:
      - data:/var/lib/redis
    configs:
      - source: config
        target: /usr/local/etc/redis.conf
        mode: 0440
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure
      resources:
        limits:
          cpus: "1"
          memory: 512M
      update_config:
        parallelism: 1
        delay: 5s
        monitor: 10s
        max_failure_ratio: 0.1
        order: start-first

configs:
  config:
    file: ./redis.conf

volumes:
  data:

networks:
   test:
     driver: overlay		
		
		

下载 配置文件 https://redis.io/topics/config

		
iMac:redis neo$ curl -sO https://raw.githubusercontent.com/redis/redis/6.0/redis.conf
iMac:redis neo$ egrep -v "^#|^$" redis.conf 
		
		

修改配置文件

		
bind 0.0.0.0
logfile "/var/log/redis/redis.log"
dir /var/lib/redis	
appendonly yes	
		
		

创建 Docker 网络

		
iMac:redis neo$ docker network create \
>   --driver=overlay \
>   --subnet=172.12.0.0/16 \
>   --ip-range=172.12.0.0/16 \
>   --gateway=172.12.0.1 \
>   --attachable \
>   test
gvcz5y66ovrlqfaxb02zx026t

iMac:redis neo$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
786efe30f42d        bridge              bridge              local
51e2b21d7daa        docker_gwbridge     bridge              local
96ba0de26cd2        host                host                local
7r7k9robn0uu        ingress             overlay             swarm
cbf078a5f121        none                null                local
d851mrlkludv        redis_default       overlay             swarm
q0h9awx86ef4        registry_default    overlay             swarm
cf585ea9ceb4        registry_default    bridge              local
gvcz5y66ovrl        test                overlay             swarm
		
iMac:redis neo$ docker stack deploy -c redis.yml redis
Creating network redis_default
Creating service redis_redis		
		
		

查看服务

		
iMac:redis neo$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
1ti2ndlpdhm8        redis_redis         replicated          0/1                 redis:latest        *:6379->6379/tcp
1w6xjrl0sn88        registry_registry   replicated          1/1                 registry:latest     *:5000->5000/tcp		
		
		

查看容器运行状态

		
iMac:redis neo$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
8407fd8fe66b        redis:latest        "docker-entrypoint.s…"   29 seconds ago      Up 29 seconds       6379/tcp            redis_redis.1.6fpqt3pdti03j9swn3x04ob9n		
		
		

1.13.3.4. somaxconn/overcommit_memory

redis 日志

		
1:C 09 Aug 2021 15:13:20.270 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 09 Aug 2021 15:13:20.270 # Redis version=6.2.5, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 09 Aug 2021 15:13:20.270 # Configuration loaded
1:M 09 Aug 2021 15:13:20.270 * monotonic clock: POSIX clock_gettime
1:M 09 Aug 2021 15:13:20.270 * Running mode=standalone, port=6379.
1:M 09 Aug 2021 15:13:20.270 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:M 09 Aug 2021 15:13:20.270 # Server initialized
1:M 09 Aug 2021 15:13:20.270 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
1:M 09 Aug 2021 15:13:20.271 * Ready to accept connections		
		
		

宿主主机上配置如下

		
[root@localhost ~]# cat >> /etc/sysctl.conf <<EOF

# Redis
net.core.somaxconn = 1024
vm.overcommit_memory=1
EOF		
		
		

docker-compose.yml 中设置 net.core.somaxconn

		
[root@localhost redis]# cat docker-compose.yml 
version: '3.9'

services:
  redis:
    image: redis:alpine
    container_name: redis
    restart: always
    hostname: redis.netkiller.cn
    user: redis:redis
    environment:
      - TZ=Asia/Shanghai
      - LANG=en_US.UTF-8
    ports:
      - 6379:6379
    volumes:
      - redis:/data
    sysctls:
      - net.core.somaxconn=511
    command: 
      --logfile /data/redis.log
      --requirepass passw0rd
      --appendonly yes
volumes:
  redis:		
		
		

1.13.4. Nginx

本例子使用 alpine 版本

1.13.4.1. nginx:latest

过程 1.1. 

  1. 				
    [root@iZj6ciilv2rcpgauqg2uuwZ]~# docker pull nginx
    Using default tag: latest
    latest: Pulling from library/nginx
    Digest: sha256:41ad9967ea448d7c2b203c699b429abe1ed5af331cd92533900c6d77490e0268
    Status: Image is up to date for nginx:latest
    				
    				
  2. 启动容器

    				
    docker run --name my-nginx-container -p 80:80 -d nginx
    				
    				

    上面不能满足生产环境的需求,通常不会将数据放在容器中,我的做法如下。

    				
    docker rm my-nginx-container -f
    docker run --name my-nginx-container \
    -v /srv/nginx/nginx.conf:/etc/nginx/nginx.conf:ro \
    -v /srv/nginx/conf.d:/etc/nginx/conf.d:ro \
    -v /var/log/nginx:/var/log/nginx:rw \
    -v /www:/www:ro \
    -p 80:80 -d nginx
    docker ps
    				
    				

1.13.4.2. 安装 Docker Nginx alpine

过程 1.2. Docker nginx

  1. 获取镜像

    				
    # docker pull nginx:alpine
    				
    				
  2. 运行容器

    				
    docker run --name my-nginx-container -v /srv/nginx:/etc/nginx:ro -v /www:/www:ro -p 80:80 -d nginx:alpine
    				
    				
  3. 				
    docker exec -it my-nginx-container /bin/bash
    				
    				

1.13.4.3. 安装依赖工具

		
apt update -y && apt install -y procps iproute2
		
		

1.13.4.4. 容器内优雅重启

首先观察一个现象,打开 linux 终端窗口,查看 nginx 进程。

		
[root@localhost ~]# ps ax | grep nginx
   6670 ?        Ss     0:00 nginx: master process /usr/sbin/nginx
   6671 ?        S      0:00 nginx: worker process
   6672 ?        S      0:00 nginx: worker process
   6673 ?        S      0:00 nginx: worker process
   6674 ?        S      0:00 nginx: worker process
   9396 pts/0    S+     0:00 grep --color=auto nginx		
		
		

6670 ~ 6674 都是 nginx 的进程,其中 6670 nginx: master process /usr/sbin/nginx 是父进程,用于监听 80/443 端口。6671 ~ 6674 nginx: worker process 是子进程,每个进程中又产生多线程,每个线程对应一次用户TCP请求。

6671 ~ 6674 子进程的进程ID会变化,而 6670 是不变的。 6670 父进程可以接收操作系统传递过来的信号(不懂信号的同学请恶补,信号,共享内存,管道,Socket 可以实现进程间通信),也就是我们可以告诉正在运行的进程,现在要干什么。

给 6670 进程发送 HUP 信号,nginx 就会重新读取配置文件,刷新缓存,此时 6671~6674不受影响,会继续为用户体统TCP链接服务,直到都安全Close为止。此时 6670 父进程已经完成配置的更新,6671~6674 也完成了它的使命,下一次新用户过来 nginx 就会创建新的进程,这个过程是无缝的,用户感知不到,80/443 端口始终提供服务,不会有任何用户出现中断链接的情况。

现在来演示一下,执行 reload 就会刷新配置文件,清空缓存,同时会将闲置的 nginx: worker process 关闭,并开启新的子进程。

		
[root@localhost ~]# systemctl reload nginx
[root@localhost ~]# ps ax | grep nginx
   6670 ?        Ss     0:00 nginx: master process /usr/sbin/nginx
   6671 ?        S      0:01 nginx: worker process is shutting down
   9403 ?        S      0:00 nginx: worker process
   9404 ?        S      0:00 nginx: worker process
   9405 ?        S      0:00 nginx: worker process
   9406 ?        S      0:00 nginx: worker process
   9408 pts/0    S+     0:00 grep --color=auto nginx		
		
		

现在我们可以看到子进程ID的变化,9403 ~ 9406。父进程 nginx: master process /usr/sbin/nginx 的ID仍然是 6670

现在是容器中实现上面的 reload 操作。

		
[root@localhost ~]# cat docker-compose.yml 
version: '3.9'
services:
  nginx:
    container_name: nginx
    restart: always
    image: nginx:latest
    ports:
      - 192.168.30.11:80:80
      - 192.168.30.11:443:443		
		
		

		
[root@localhost ~]# docker-compose up
Starting nginx ... done
Attaching to nginx
nginx    | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
nginx    | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
nginx    | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
nginx    | 10-listen-on-ipv6-by-default.sh: info: IPv6 listen already enabled
nginx    | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
nginx    | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
nginx    | /docker-entrypoint.sh: Configuration complete; ready for start up
nginx    | 2021/07/12 20:55:41 [notice] 1#1: using the "epoll" event method
nginx    | 2021/07/12 20:55:41 [notice] 1#1: nginx/1.21.1
nginx    | 2021/07/12 20:55:41 [notice] 1#1: built by gcc 8.3.0 (Debian 8.3.0-6) 
nginx    | 2021/07/12 20:55:41 [notice] 1#1: OS: Linux 4.18.0-315.el8.x86_64
nginx    | 2021/07/12 20:55:41 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
nginx    | 2021/07/12 20:55:41 [notice] 1#1: start worker processes
nginx    | 2021/07/12 20:55:41 [notice] 1#1: start worker process 24
nginx    | 2021/07/12 20:55:41 [notice] 1#1: start worker process 25
nginx    | 2021/07/12 20:55:41 [notice] 1#1: start worker process 26
nginx    | 2021/07/12 20:55:41 [notice] 1#1: start worker process 27		
		
		

		
[root@localhost ~]# docker exec -it nginx bash
root@2d2637a6ac4d:/# ps ax
    PID TTY      STAT   TIME COMMAND
      1 ?        Ss     0:00 nginx: master process nginx -g daemon off;
     24 ?        S      0:00 nginx: worker process
     25 ?        S      0:00 nginx: worker process
     26 ?        S      0:00 nginx: worker process
     27 ?        S      0:00 nginx: worker process
    623 pts/0    Ss     0:00 bash
    629 pts/0    R+     0:00 ps ax
root@2d2637a6ac4d:/# 		
		
		

reload nginx

		
[root@localhost ~]# docker ps 
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS         PORTS                                                  NAMES
2d2637a6ac4d   nginx:latest   "/docker-entrypoint.…"   25 minutes ago   Up 5 minutes   192.168.30.11:80->80/tcp, 192.168.30.11:443->443/tcp   nginx
[root@localhost ~]# docker container exec nginx  nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@localhost ~]# docker container exec nginx  nginx -s reload
2021/07/12 21:01:41 [notice] 636#636: signal process started		
		
		

再次查看进程

		
[root@localhost ~]# docker exec -it nginx bash
root@2d2637a6ac4d:/# ps ax
    PID TTY      STAT   TIME COMMAND
      1 ?        Ss     0:00 nginx: master process nginx -g daemon off;
     24 ?        S      0:00 nginx: worker process
     25 ?        S      0:00 nginx: worker process
     26 ?        S      0:00 nginx: worker process
     27 ?        S      0:00 nginx: worker process
    623 pts/0    Ss     0:00 bash
    629 pts/0    R+     0:00 ps ax

root@2d2637a6ac4d:/# ps ax
    PID TTY      STAT   TIME COMMAND
      1 ?        Ss     0:00 nginx: master process nginx -g daemon off;
    623 pts/0    Ss     0:00 bash
    642 ?        S      0:00 nginx: worker process
    643 ?        S      0:00 nginx: worker process
    644 ?        S      0:00 nginx: worker process
    645 ?        S      0:00 nginx: worker process
    646 pts/0    R+     0:00 ps ax		
		
		

1.13.5. MySQL

	
sudo mkdir -p /opt/mysql/{data,mysql.d,docker-entrypoint-initdb.d}
	
	

docker-compose.yaml

	
version: '3'

services:
  mysql:
    # 镜像名
    image: mysql:latest
    # 容器名
    container_name: mysql
    # 重启策略
    restart: always
    hostname: db.netkiller.cn
    environment:
      # 时区上海
      TZ: Asia/Shanghai
      # root 密码
      MYSQL_ROOT_PASSWORD: test
      # 初始化数据库
      MYSQL_DATABASE: test
      # 初始普通化用户
      MYSQL_USER: test
      # 用户密码
      MYSQL_PASSWORD: test
      # 映射端口
    ports:
      - 3306:3306
    volumes:
      # 挂载数据
      - ./mysql/data/:/var/lib/mysql/
      # 挂载配置
      - ./mysql/conf.d/:/etc/mysql/conf.d/
      # 挂载初始化目录
      - ./mysql/docker-entrypoint-initdb.d/:/docker-entrypoint-initdb.d/
    command:
      --default-authentication-plugin=mysql_native_password
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_general_ci
      --explicit_defaults_for_timestamp=true
      --lower_case_table_names=1
	
	

登陆测试

	
neo@MacBook-Pro-Neo ~ % docker exec -it mysql mysql -uroot -ptest
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 8.0.25 MySQL Community Server - GPL

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 
	
	

1.13.6. MongoDB

	
$ docker run -d --network some-network --name mongo \
	-e MONGO_INITDB_DATABASE=test \
    -e MONGO_INITDB_ROOT_USERNAME=admin \
    -e MONGO_INITDB_ROOT_PASSWORD=secret \
    mongo

$ docker run -it --rm --network some-network mongo \
    mongo --host mongo \
        -u admin \
        -p secret \
        --authenticationDatabase admin \
        test
> db.getName();
test
	
	

1.13.6.1. 使用 mongodb 用户运行

		
version: '3.9'
services:
  mongodb:
    image: mongo:latest
    container_name: mongo
    hostname: mongo.netkiller.cn
    restart: always
    user: mongodb:mongodb
    privileged: false
    volumes:
      - ./data:/data
    ports:
      - 27017:27017
    environment:
      TZ: Asia/Shanghai
      LANG: en_US.UTF-8
      MONGO_INITDB_DATABASE: admin
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: admin
    entrypoint: docker-entrypoint.sh mongod
    command: 
      --logpath /data/mongod.log	
		
		

1.13.6.2. 

		
[www@testing ~]$ sudo  cat /var/log/mongodb/mongod.log | grep '"W"'
{"t":{"$date":"2021-08-13T19:54:20.219+08:00"},"s":"W",  "c":"ASIO",     "id":22601,   "ctx":"main","msg":"No TransportLayer configured during NetworkInterface startup"}
{"t":{"$date":"2021-08-13T19:54:20.227+08:00"},"s":"W",  "c":"ASIO",     "id":22601,   "ctx":"main","msg":"No TransportLayer configured during NetworkInterface startup"}
{"t":{"$date":"2021-08-13T19:54:20.851+08:00"},"s":"W",  "c":"CONTROL",  "id":22178,   "ctx":"initandlisten","msg":"/sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never'","tags":["startupWarnings"]}
{"t":{"$date":"2021-08-13T20:01:12.470+08:00"},"s":"W",  "c":"ASIO",     "id":22601,   "ctx":"main","msg":"No TransportLayer configured during NetworkInterface startup"}
{"t":{"$date":"2021-08-13T20:01:12.478+08:00"},"s":"W",  "c":"ASIO",     "id":22601,   "ctx":"main","msg":"No TransportLayer configured during NetworkInterface startup"}
{"t":{"$date":"2021-08-13T20:01:13.085+08:00"},"s":"W",  "c":"CONTROL",  "id":22178,   "ctx":"initandlisten","msg":"/sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never'","tags":["startupWarnings"]}		
		
		
		
[root@testing ~]# docker exec -it mongo bash
root@mongo:/# cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
root@mongo:/# cat /sys/kernel/mm/transparent_hugepage/defrag
always defer defer+madvise [madvise] never		
		
		
		
root@mongo:/# echo never > /sys/kernel/mm/transparent_hugepage/defrag
bash: /sys/kernel/mm/transparent_hugepage/defrag: Read-only file system		
		
		
		
[root@testing ~]# if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
>   echo never > /sys/kernel/mm/transparent_hugepage/enabled
> fi

[root@testing ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]

[root@testing ~]# docker exec -it mongo bash
root@mongo:/# cat /sys/kernel/mm/transparent_hugepage/defrag
always defer defer+madvise [madvise] never

root@mongo:/# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]
root@mongo:/# exit
exit		
		
		

解决方案 /etc/rc.local 中加入下面脚本,CentOS 8 Stream 开启 rc.local 请参考《Netkiller Linux 手札》

		
cat <<'EOF'>> /etc/rc.local 
		
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
	echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi

if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
	echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
EOF
		
		

		
[root@testing ~]# systemctl restart rc-local
		
		

1.13.7. Node

		
version: '3.9'
services:		
  node:
    image: node:latest
    container_name: node
    restart: always
    hostname: node.netkiller.cn
    extra_hosts:
      - db.netkiller.cn:192.168.10.5
      - redis.netkiller.cn:192.168.10.12
    environment:
      TZ: Asia/Shanghai
    ports:
      - 7777:7777
    volumes:
      - /opt/netkiller.cn/www.netkiller.cn:/opt/netkiller.cn/www.netkiller.cn
    working_dir: /opt/netkiller.cn/www.netkiller.cn
    entrypoint: node /opt/netkiller.cn/www.netkiller.cn/main.js