Server Docker Deployment Record

📢 This article was translated by gemini-3-flash-preview

It took three months from the initial idea to full implementation (mostly because I was too lazy).

Installing Docker

Installed using APT (on Debian).

  1. Add packages for HTTPS transport and CA certificates.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Update first
sudo apt-get update

# Then install
sudo apt-get install \
     apt-transport-https \
     ca-certificates \
     curl \
     gnupg \
     lsb-release
  1. Add the GPG key for the software source to verify package legitimacy.
1
2
3
4
5
6
# China mirror
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg


# Official source
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
  1. Add the Docker repository to sources.list.

First, determine your Debian version name, then replace $(lsb_release -cs) in the command below.

You can find version names at https://mirrors.aliyun.com/docker-ce/linux/debian/dists/ .

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# China mirror
echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/debian \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null


# Official source
echo \
   "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
   $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

For example, Debian 10 is buster, and Debian 11 is bullseye.

1
2
3
4
# This is for Debian 11
echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/debian \
  bullseye stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

The commands above add the stable Docker APT source. If you need the test version, change stable to test.

  1. Now install.
1
2
3
4
5
6
7
8
# Update cache
sudo apt-get update

# Install docker
sudo apt-get install docker-ce docker-ce-cli containerd.io

# Install docker-compose
sudo apt-get install docker-compose

Alternatively, you can try the one-click installation script:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Test version
curl -fsSL test.docker.com -o get-docker.sh

# Stable version
curl -fsSL get.docker.com -o get-docker.sh

# Aliyun mirror
sudo sh get-docker.sh --mirror Aliyun

# Microsoft Azure China mirror
sudo sh get-docker.sh --mirror AzureChinaCloud

Starting Docker

1
2
sudo systemctl enable docker
sudo systemctl start docker

Test if it’s running correctly with:

1
docker run --rm hello-world

If you see output like this, the installation was successful:

 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
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:c77be1d3a47d0caf71a82dd893ee61ce01f32fc758031a6ec4cf1389248bb833
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Blog 1: WordPress

Create a folder (e.g., /root/wordpress), then create a docker-compose.yml file:

 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
version: '3.3'
services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress
   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     volumes:
       - /root/wordpress/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
     ports:
       - 8000:80
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
       WORDPRESS_DB_NAME: wordpress
volumes:
    db_data: {}

Create an uploads.ini file:

1
2
3
4
5
file_uploads = On
memory_limit = 256M
upload_max_filesize = 10M
post_max_size = 10M
max_execution_time = 600

Docker Container Operations

1
2
3
4
5
6
7
8
# Run in background
docker-compose up -d

# Stop
docker-compose stop

# Stop and remove
docker-compose down

Blog 2: Typecho

Using image: 80x86/typecho

Create the folder and corresponding file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
version: '3.0'
services:
    typecho:
        image: 80x86/typecho:latest
        container_name: Typecho_Blog
        volumes:
            - /root/typecho/data:/data
        ports:
            - 8001:80
        restart: always
        environment:
            PHP_TZ: Asia/Shanghai
            PHP_MAX_EXECUTION_TIME: 600

Netdisk Site

Using project: https://github.com/px-org/PanIndex

Official tutorial: https://docs.noki.icu/

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
version: "3.0"
services:
  PanIndex:
    restart: always
    image: iicm/pan-index:latest
    container_name: VRC_Pan
    volumes:
      - /root/pan/data:/app/data
    ports:
      - 8002:5238

Nginx and SSL Certificates

Using project: https://github.com/0xJacky/nginx-ui

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
version: '3.1' 
services: 
  nginx-ui:
    restart: always
    image: uozi/nginx-ui:latest
    container_name: nginx_UI
    volumes:
      - /root/nginx/nginx:/etc/nginx
      - /root/nginx/nginx-ui:/etc/nginx-ui
      - /root/nginx/www:/www
    ports:
      - 80:80
      - 443:443

When proxying the host machine in the configuration, you can use the host IP as 172.17.0.1.

You can verify this with:

1
ip addr show docker0

The GUI is straightforward.

Entering a Container

  1. Get the container ID:
1
docker container ls
  1. Enter:
1
docker exec -i [ID] bash

Then you can use bash commands (though there is no bash prompt).

For Reference Only

Configuring Nginx and SSL manually took the longest and kept failing, so I switched to the GUI.

SSL Certificates

Used neilpang/acme.sh with DNS verification. For other methods, see Run acme.sh in docker · acmesh-official/acme.sh Wiki (github.com) .

Create folders and the file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
version: '3.1' 
services: 
  acme.sh:
    image: neilpang/acme.sh
    container_name: acme.sh    
    command: daemon
    volumes:
      - /root/acme/acme.sh:/acme.sh
      - /root/acme/conf:/.acme.sh
    environment:
      - CF_Key="Your_CF_API_Key"
      - CF_Email="Your_CF_Email"

For other DNS providers, refer to: https://github.com/acmesh-official/acme.sh/wiki/dnsapi

Register an account:

1
docker exec acme.sh --register-account -m [email protected]

Obtain certificate (using CF here):

1
docker exec acme.sh --issue --dns dns_cf -d example.com -d www.example.com

The paths for the certificate and storage will be printed. Map this directory to the Nginx container.

You can set up a cron job to auto-renew certificates. Reference: Linux Crontab Tasks - Runoob


References:

Docker obtaining Let’s Encrypt free SSL certificates - Tencent Cloud

ZeroSSL.com CA · acmesh-official/acme.sh Wiki (github.com)


Nginx

Create folder (e.g., /root/nginx), then create docker-compose.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
version: '3.1' 
services: 
  nginx:
    restart: always 
    image: nginx
    container_name: nginx
    ports:
      - 80:80
    volumes:
      - /root/docker/nginx/conf.d:/etc/nginx/conf.d
      - /root/docker/nginx/www:/user/share/nfinx/html
      - /root/docker/nginx/log:/var/log/nginx
      - /root/acme/acme.sh:/ssl

After starting, you will find a conf.d folder. Create a new .conf file inside, such as default.conf:

 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
server {
    listen          80;
    listen          [::]:80;

    server_name     <your_server_name>;
    rewrite ^(.*)$  https://$host$1 permanent;
}

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen  443       ssl http2;
    listen  [::]:443  ssl http2;

    server_name         <your_server_name>;

    # SSL cert location
    ssl_certificate     /path/to/ssl_cert;
    # SSL key location
    ssl_certificate_key /path/to/ssl_cert_key;

    location / {
        proxy_set_header    Host                $host;
        proxy_set_header    X-Real-IP           $remote_addr;
        proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto   $scheme;
        proxy_http_version  1.1;
        proxy_set_header    Upgrade             $http_upgrade;
        proxy_set_header    Connection          $connection_upgrade;
        proxy_pass          http://172.17.0.1:9000/;
    }
}

References:

Docker Nginx SSL and Host Proxy

Nginx SSL Configuration Detailed Guide - Aliyun

Docker Deploy Multiple Sites - CSDN

Let’s Encrypt HTTPS Tutorial - Diamond-Blog

Nginx Reverse Proxy Summary - Jianshu

Nginx Hide Port with Reverse Proxy - Blog Garden


References

Debian - Docker — Practice Guide (gitbook.io)

Install WordPress with Docker - Tencent Cloud

Solving WordPress upload_max_filesize in Docker - CSDN

Let’s Encrypt Could not bind to IPv4 or IPv6 - Liaosam

Let’s Encrypt Multi-domain and Wildcard Certs - Blog Garden

Docker Compose - Runoob

Nginx Config File Explained - Blog Garden

Using acme.sh in Docker for SSL - Moeelf

Installing Nginx with Docker and SSL configuration for Host Proxy

This post is licensed under CC BY-NC-SA 4.0 by the author.
Last updated on 2025-10-03 03:27 +0900