mirror of
https://github.com/ggogel/seafile-containerized.git
synced 2024-11-16 09:01:38 +00:00
Support native docker run instead of using the launcher script (#47)
* didn't use launcher * travis * link error & update readme * del launcher.ps1, del bootstrap func under launcher file * [readme] password/plan b, add a new admin * review
This commit is contained in:
parent
22457f2327
commit
9c3fdcae32
149
README.dev.md
Normal file
149
README.dev.md
Normal file
|
@ -0,0 +1,149 @@
|
|||
[![Build Status](https://secure.travis-ci.org/haiwen/seafile-docker.png?branch=master)](http://travis-ci.org/haiwen/seafile-docker)
|
||||
|
||||
### About
|
||||
|
||||
- [Docker](https://docker.com/) is an open source project to pack, ship and run any Linux application in a lighter weight, faster container than a traditional virtual machine.
|
||||
|
||||
- Docker makes it much easier to deploy [a Seafile server](https://github.com/haiwen/seafile) on your servers and keep it updated.
|
||||
|
||||
- The base image configures Seafile with the Seafile team's recommended optimal defaults.
|
||||
|
||||
### Getting Started
|
||||
|
||||
Generate seafile image, and run the image.
|
||||
|
||||
```
|
||||
sudo git clone https://github.com/haiwen/seafile-docker.git /var/seafile/
|
||||
cd /var/seafile/image
|
||||
|
||||
make base
|
||||
make server
|
||||
docker run -d --name seafile-server -v /root/seafile:/shared -p 80:80 seafileltd/seafile:6.2.1
|
||||
```
|
||||
|
||||
Now visit `http://hostname` or `https://hostname` to open Seafile Web UI.
|
||||
|
||||
If you are not familiar with docker commands, refer to [docker documentation](https://docs.docker.com/engine/reference/commandline/cli/).
|
||||
|
||||
### How to use
|
||||
|
||||
#### Custom admin username and password
|
||||
|
||||
The default account is `me@example.com` and the password is `asecret`.
|
||||
You must change the password when you first run the seafile server.
|
||||
If you forget the admin password, you can add a new admin account and then go to the sysadmin panel to reset user password.
|
||||
|
||||
#### Domain
|
||||
|
||||
You can create `/shared/bootstrap.conf`, write the following lines.
|
||||
|
||||
[server]
|
||||
server.hostname = seafile.example.com
|
||||
|
||||
And then restart service, nginx will update up config.
|
||||
|
||||
#### Modify configurations
|
||||
|
||||
The config files are under `shared/seafile/conf`. You can modify the configurations according to [Seafile manual](https://manual.seafile.com/)
|
||||
|
||||
After modification, run the new docker container:
|
||||
|
||||
```
|
||||
docker rm -f seafile-server
|
||||
docker run -d --name seafile-server -v /root/seafile:/shared -p 80:80 seafileltd/seafile:6.2.1
|
||||
```
|
||||
|
||||
#### Find logs
|
||||
|
||||
The seafile logs are under `shared/logs/seafile`.
|
||||
|
||||
The system logs are under `shared/logs/var-log`.
|
||||
|
||||
#### Add a new Admin
|
||||
|
||||
Enter the command below.
|
||||
|
||||
```
|
||||
docker exec -it seafile-server /opt/seafile/seafile-server-latest/reset-admin.sh
|
||||
```
|
||||
|
||||
Enter the username and password according to the prompts.You now have a new admin account.
|
||||
|
||||
### Directory Structure
|
||||
|
||||
#### `/bootstrap`
|
||||
|
||||
This directory is for container definitions for your Seafile containers. You are in charge of this directory, it ships empty.
|
||||
|
||||
#### `/samples`
|
||||
|
||||
Sample container definitions you may use to bootstrap your environment. You can copy templates from here into the bootstrap directory.
|
||||
|
||||
#### `/shared`
|
||||
|
||||
Placeholder spot for shared volumes. You may elect to store certain persistent information outside of a container, in our case we keep various logfiles and upload directory outside. This allows you to rebuild containers easily without losing important information.
|
||||
|
||||
- /shared/db: This is the data directory for mysql server
|
||||
- /shared/seafile: This is the directory for seafile server configuration and data.
|
||||
- /shared/logs: This is the directory for logs.
|
||||
- /shared/logs/var-log: This is the directory that would be mounted as `/var/log` inside the container. For example, you can find the nginx logs in `shared/logs/var-log/nginx/`.
|
||||
- /shared/logs/seafile: This is the directory that would contain the log files of seafile server processes. For example, you can find seaf-server logs in `shared/logs/seafile/seafile.log`.
|
||||
- /shared/ssl: This is directory for certificate, which does not exist by default.
|
||||
- /shared/bootstrap.conf: This file does not exist by default. You can create it by your self, and write the configuration of files similar to the `samples` folder.
|
||||
|
||||
#### `/templates`
|
||||
|
||||
Various jinja2 templates used for seafile server configuration.
|
||||
|
||||
#### `/image`
|
||||
|
||||
Dockerfiles for Seafile.
|
||||
|
||||
The Docker repository will always contain the latest built version at: https://hub.docker.com/r/seafileltd/seafile/, you should not need to build the base image.
|
||||
|
||||
### Container Configuration
|
||||
|
||||
#### Let's encrypt SSL certificate
|
||||
|
||||
If you set `server.letsencrypt` to `true`, the bootstrap script would request a letsencrypt-signed SSL certificate for you.
|
||||
|
||||
```conf
|
||||
server.letsencrypt = true
|
||||
```
|
||||
|
||||
If you want to use your own SSL certificate:
|
||||
- create a folder 'shared/ssl', and put your certificate and private key under the ssl directory.
|
||||
- Assume your site name is "seafile.example.com", then your certificate must have the name "seafile.example.com.crt", and the private key must have the name "seafile.example.com.key".
|
||||
|
||||
### Upgrading Seafile Server
|
||||
|
||||
ensure same version of the repo, and run start command`docker run -d --name seafile-server -v /root/seafile:/shared -p 80:80 seafileltd/seafile:6.2.1 `, which would keep your seafile server up to date.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
You can run the command as "docker logs" or "docker exec" to find errors.
|
||||
|
||||
### Developing with Vagrant
|
||||
|
||||
If you are looking to make modifications to this repository, you can easily test
|
||||
out your changes before committing, using the magic
|
||||
of [Vagrant](http://vagrantup.com). Install Vagrant as
|
||||
per
|
||||
[the default instructions](http://docs.vagrantup.com/v2/installation/index.html),
|
||||
and then run:
|
||||
|
||||
vagrant up
|
||||
|
||||
This will spawn a new Ubuntu VM, install Docker, and then await your
|
||||
instructions. You can then SSH into the VM with `vagrant ssh`, become `root`
|
||||
with `sudo -i`, and then you're right to go. Your live git repo is already
|
||||
available at `/var/seafile`, so you can just `cd /var/seafile` and then start
|
||||
running `launcher`.
|
||||
|
||||
### Special Thanks
|
||||
|
||||
Lots of the design of this repo is borrowed from the excellent [discourse-docker](https://github.com/discourse/discourse_docker) project. Thanks for their insipiration!
|
||||
|
||||
License
|
||||
===
|
||||
Apache
|
154
README.md
154
README.md
|
@ -10,53 +10,80 @@
|
|||
|
||||
### Getting Started
|
||||
|
||||
The simplest way to get started is via the **samples/server.conf** template, which can be installed within several minutes.
|
||||
Download seafile image, and run the image.
|
||||
|
||||
```
|
||||
sudo git clone https://github.com/haiwen/seafile-docker.git /var/seafile/
|
||||
cd /var/seafile/
|
||||
|
||||
sudo cp samples/server.conf bootstrap/bootstrap.conf
|
||||
# Edit the options according to your use case
|
||||
sudo vim bootstrap/bootstrap.conf
|
||||
|
||||
sudo ./launcher bootstrap
|
||||
sudo ./launcher start
|
||||
docker run -d --name seafile-server -v /opt/seafile-data:/shared -p 80:80 seafileltd/seafile:6.2.1
|
||||
```
|
||||
|
||||
Now visit `http://hostname` or `https://hostname` to open Seafile Web UI.
|
||||
|
||||
### How to use
|
||||
If you are not familiar with docker commands, refer to [docker documentation](https://docs.docker.com/engine/reference/commandline/cli/).
|
||||
|
||||
### More configuration option
|
||||
|
||||
#### Custom admin username and password
|
||||
|
||||
The default account is `me@example.com` and the password is `asecret`. It will be created when the container is first run.
|
||||
The default values can also be changed by setting the container's environment variables
|
||||
|
||||
e.g.
|
||||
|
||||
docker run -d --name seafile-server -e "SEAFILE_ADMIN_EMAIL=me@example.com" -e "SEAFILE_ADMIN_PASSWORD=asecret" -v /opt/seafile-data:/shared -p 80:80 seafileltd/seafile:6.2.1
|
||||
|
||||
If you forget the admin password, you can add a new admin account and then go to the sysadmin panel to reset user password.
|
||||
|
||||
#### Domain
|
||||
|
||||
The default value is `seafile.example.com`, you can set environ to docker container.
|
||||
|
||||
e.g.
|
||||
|
||||
docker run -d --name seafile-server -e "SEAFILE_SERVER_HOSTNAME=seafile.example.com" -v /opt/seafile-data:/shared -p 80:80 seafileltd/seafile:6.2.1
|
||||
|
||||
And then nginx will update up config.
|
||||
|
||||
#### Let's encrypt SSL certificate
|
||||
|
||||
If you set `SEAFILE_SERVER_LETSENCRYPT` to `true`, the bootstrap script would request a letsencrypt-signed SSL certificate for you.
|
||||
|
||||
e.g.
|
||||
|
||||
docker run -d --name seafile-server -e "SEAFILE_SERVER_LETSENCRYPT=true" -v /opt/seafile-data:/shared -p 80:80 -p 443:443 seafileltd/seafile:6.2.1
|
||||
|
||||
If you want to use your own SSL certificate:
|
||||
- create a folder 'shared/ssl', and put your certificate and private key under the ssl directory.
|
||||
- Assume your site name is "seafile.example.com", then your certificate must have the name "seafile.example.com.crt", and the private key must have the name "seafile.example.com.key".
|
||||
|
||||
#### Modify configurations
|
||||
|
||||
The config files are under `shared/seafile/conf`. You can modify the configurations according to [Seafile manual](https://manual.seafile.com/)
|
||||
|
||||
After modification, restart the docker container:
|
||||
After modification, run the new docker container:
|
||||
|
||||
```
|
||||
sudo ./launcher restart
|
||||
docker rm -fseafile-server
|
||||
docker run -d --name seafile-server -v /root/seafile:/shared -p 80:80 seafileltd/seafile:6.2.1
|
||||
```
|
||||
|
||||
#### Find logs
|
||||
|
||||
The logs are under `shared/logs/seafile`.
|
||||
The seafile logs are under `shared/logs/seafile`.
|
||||
|
||||
#### Enable debug logs of launcher
|
||||
The system logs are under `shared/logs/var-log`.
|
||||
|
||||
Pass `-v` to launcher script (for example `sudo ./launcher -v rebuild` would make it print more verbose information
|
||||
#### Add a new Admin
|
||||
|
||||
Enter the command below.
|
||||
|
||||
```
|
||||
docker exec -it seafile-server /opt/seafile/seafile-server-latest/reset-admin.sh
|
||||
```
|
||||
|
||||
Enter the username and password according to the prompts.You now have a new admin account.
|
||||
|
||||
### Directory Structure
|
||||
|
||||
#### `/bootstrap`
|
||||
|
||||
This directory is for container definitions for your Seafile containers. You are in charge of this directory, it ships empty.
|
||||
|
||||
#### `/samples`
|
||||
|
||||
Sample container definitions you may use to bootstrap your environment. You can copy templates from here into the bootstrap directory.
|
||||
|
||||
#### `/shared`
|
||||
|
||||
Placeholder spot for shared volumes. You may elect to store certain persistent information outside of a container, in our case we keep various logfiles and upload directory outside. This allows you to rebuild containers easily without losing important information.
|
||||
|
@ -66,84 +93,21 @@ Placeholder spot for shared volumes. You may elect to store certain persistent i
|
|||
- /shared/logs: This is the directory for logs.
|
||||
- /shared/logs/var-log: This is the directory that would be mounted as `/var/log` inside the container. For example, you can find the nginx logs in `shared/logs/var-log/nginx/`.
|
||||
- /shared/logs/seafile: This is the directory that would contain the log files of seafile server processes. For example, you can find seaf-server logs in `shared/logs/seafile/seafile.log`.
|
||||
- /shared/ssl: This is directory for certificate, which does not exist by default.
|
||||
- /shared/bootstrap.conf: This file does not exist by default. You can create it by your self, and write the configuration of files similar to the `samples` folder.
|
||||
|
||||
#### `/templates`
|
||||
|
||||
Various jinja2 templates used for seafile server configuration.
|
||||
|
||||
#### `/image`
|
||||
|
||||
Dockerfiles for Seafile.
|
||||
|
||||
The Docker repository will always contain the latest built version at: https://hub.docker.com/r/seafileltd/seafile/, you should not need to build the base image.
|
||||
|
||||
### Launcher
|
||||
|
||||
The base directory contains a single bash script which is used to manage containers. You can use it to "bootstrap" a new container, enter, start, stop and destroy a container.
|
||||
|
||||
```
|
||||
Usage: launcher COMMAND
|
||||
Commands:
|
||||
bootstrap: Bootstrap a container for the config based on a template
|
||||
start: Start/initialize a container
|
||||
stop: Stop a running container
|
||||
restart: Restart a container
|
||||
destroy: Stop and remove a container
|
||||
enter: Use docker exec to enter a container
|
||||
logs: Docker logs for container
|
||||
rebuild: Rebuild a container (destroy old, bootstrap, start new)
|
||||
gc: Start the seafile garbage collector (stops seafile, starts gc, restarts seafile)
|
||||
```
|
||||
|
||||
If the environment variable "SUPERVISED" is set to true, the container won't be detached, allowing a process monitoring tool to manage the restart behaviour of the container.
|
||||
|
||||
### Container Configuration
|
||||
|
||||
#### port mapping:
|
||||
|
||||
```conf
|
||||
server.port_mappings = 80:80,443:443
|
||||
```
|
||||
|
||||
#### Let's encrypt SSL certificate
|
||||
|
||||
If you set `server.letsencrypt` to `true`, the bootstrap script would request a letsencrypt-signed SSL certificate for you.
|
||||
|
||||
```conf
|
||||
server.letsencrypt = true
|
||||
server.port_mappings = 80:80,443:443
|
||||
```
|
||||
|
||||
If you want to use your own SSL certificate:
|
||||
- create a folder 'shared/ssl', and put your certificate and private key under the ssl directory.
|
||||
- Assume your site name is "seafile.example.com", then your certificate must have the name "seafile.example.com.crt", and the private key must have the name "seafile.example.com.key".
|
||||
|
||||
### Upgrading Seafile Server
|
||||
If you are one of the users who use the launcher update. You can refer to [upgrade from old format](https://github.com/haiwen/seafile-docker/upgrade_from_old_format.md)
|
||||
|
||||
Simple run `sudo ./launcher rebuild`, which would keep your seafile server up to date.
|
||||
ensure same version of the repo, and run start command
|
||||
|
||||
docker run -d --name seafile-server -v ${data_path}:/shared -p 80:80 seafileltd/seafile:6.2.1
|
||||
which would keep your seafile server up to date.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
View the container logs: `sudo ./launcher logs`
|
||||
|
||||
Spawn a shell inside your container using `sudo ./launcher enter`. This is the most foolproof method if you have host root access.
|
||||
|
||||
### Developing with Vagrant
|
||||
|
||||
If you are looking to make modifications to this repository, you can easily test
|
||||
out your changes before committing, using the magic
|
||||
of [Vagrant](http://vagrantup.com). Install Vagrant as
|
||||
per
|
||||
[the default instructions](http://docs.vagrantup.com/v2/installation/index.html),
|
||||
and then run:
|
||||
|
||||
vagrant up
|
||||
|
||||
This will spawn a new Ubuntu VM, install Docker, and then await your
|
||||
instructions. You can then SSH into the VM with `vagrant ssh`, become `root`
|
||||
with `sudo -i`, and then you're right to go. Your live git repo is already
|
||||
available at `/var/seafile`, so you can just `cd /var/seafile` and then start
|
||||
running `launcher`.
|
||||
You can run the command as "docker logs" or "docker exec" to find errors.
|
||||
|
||||
### Special Thanks
|
||||
|
||||
|
|
|
@ -55,13 +55,8 @@ Now run the following commands:
|
|||
(Note that if you're using another drive than "C:", say "D:", you should change the "c:\\seafile" in the following commands to "d:\\seafile" instead.)
|
||||
|
||||
```sh
|
||||
git clone https://github.com/haiwen/seafile-docker.git c:\seafile
|
||||
cd c:\seafile
|
||||
|
||||
Copy-Item samples/server.conf bootstrap/bootstrap.conf
|
||||
# Edit the options according to your use case
|
||||
start notepad++ bootstrap/bootstrap.conf
|
||||
|
||||
.\launcher.ps1 bootstrap
|
||||
.\launcher.ps1 start
|
||||
docker pull seafileltd/seafile:6.2.1
|
||||
docker run -d --name seafile-server -v /root/seafile:/shared -p 80:80 seafileltd/seafile:6.2.1
|
||||
```
|
||||
|
||||
If you are not familiar with docker commands, refer to [docker documentation](https://docs.docker.com/engine/reference/commandline/cli/).
|
||||
|
|
16
ci/ci.sh
16
ci/ci.sh
|
@ -1,5 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
version=6.2.3
|
||||
set -e -x
|
||||
|
||||
|
||||
|
@ -7,18 +8,15 @@ set -e -x
|
|||
cd image
|
||||
# pip install docker-squash
|
||||
# make base squash-base server
|
||||
make base
|
||||
make server
|
||||
)
|
||||
|
||||
sudo cp samples/server.conf bootstrap/bootstrap.conf
|
||||
|
||||
sudo ./launcher -v bootstrap
|
||||
sudo ./launcher -v start && sleep 10
|
||||
sudo ./launcher stop --skip-prereqs
|
||||
sudo ./launcher start --docker-args "--memory 1g" && sleep 10
|
||||
sudo ./launcher restart
|
||||
sudo ./launcher -v rebuild
|
||||
sudo ./launcher -v rebuild --docker-args "--memory 1g"
|
||||
mkdir -p /opt/seafile-docker-data
|
||||
docker run -d --name seafile-server -v /opt/seafile-docker-data:/shared -p 80:80 -p 443:443 seafileltd/seafile:$version
|
||||
docker stop seafile-server
|
||||
docker start seafile-server
|
||||
docker restart seafile-server
|
||||
|
||||
if [[ $TRAVIS_TAG != "" ]]; then
|
||||
ci/publish-image.sh
|
||||
|
|
|
@ -14,4 +14,10 @@ RUN mkdir -p /opt/seafile/ && \
|
|||
curl -sSL -o - https://download.seadrive.org/seafile-server_${SEAFILE_VERSION}_x86-64.tar.gz \
|
||||
| tar xzf - -C /opt/seafile/
|
||||
|
||||
ADD create_data_links.sh /etc/my_init.d/create_data_links.sh
|
||||
ADD create_data_links.sh /etc/my_init.d/01_create_data_links.sh
|
||||
|
||||
COPY scripts /scripts
|
||||
COPY templates /templates
|
||||
COPY bootstrap.conf /opt/bootstrap.conf
|
||||
|
||||
CMD ["/sbin/my_init", "--", "/scripts/start.py"]
|
||||
|
|
8
image/seafile/bootstrap.conf
Normal file
8
image/seafile/bootstrap.conf
Normal file
|
@ -0,0 +1,8 @@
|
|||
# If you edit this file, remember to run ./launcher rebuild
|
||||
[server]
|
||||
server.hostname = seafile.example.com
|
||||
admin.email = me@example.com
|
||||
admin.password = asecret
|
||||
|
||||
# uncomment the one lines below to use letsencrypt SSL certificate
|
||||
# server.letsencrypt = true
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
if [[ $SEAFILE_BOOTSRAP != "" ]]; then
|
||||
|
@ -12,32 +12,50 @@ dirs=(
|
|||
ccnet
|
||||
seafile-data
|
||||
seahub-data
|
||||
bootstrap.conf
|
||||
)
|
||||
|
||||
for d in ${dirs[*]}; do
|
||||
src=/shared/seafile/$d
|
||||
if [[ -e $src ]]; then
|
||||
ln -sf $src /opt/seafile/
|
||||
ln -sf $src /opt/seafile
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ! -e /shared/logs/seafile ]]; then
|
||||
mkdir -p /shared/logs/seafile
|
||||
fi
|
||||
if [[ -e /shared/logs/seafile ]]; then
|
||||
ln -sf /shared/logs/seafile/ /opt/seafile/logs
|
||||
rm /opt/seafile/logs && ln -sf /shared/logs/seafile/ /opt/seafile/logs
|
||||
fi
|
||||
|
||||
current_version_dir=/opt/seafile/seafile-server-${SEAFILE_VERSION}
|
||||
latest_version_dir=/opt/seafile/seafile-server-latest
|
||||
seahub_data_dir=/shared/seafile/seahub-data
|
||||
|
||||
if [[ ! -e ${latest_version_dir} ]]; then
|
||||
ln -sf ${current_version_dir} ${latest_version_dir}
|
||||
if [[ ! -e ${seahub_data_dir} ]]; then
|
||||
mkdir -p ${seahub_data_dir}
|
||||
fi
|
||||
|
||||
source_avatars_dir=${current_version_dir}/seahub/media/avatars
|
||||
rm -rf $source_avatars_dir
|
||||
ln -sf ${seahub_data_dir}/avatars $source_avatars_dir
|
||||
if [[ ! -e ${seahub_data_dir}/avatars ]]; then
|
||||
mv $source_avatars_dir ${seahub_data_dir}/avatars
|
||||
fi
|
||||
rm -rf $source_avatars_dir && ln -sf ${seahub_data_dir}/avatars $source_avatars_dir
|
||||
|
||||
source_custom_dir=${current_version_dir}/seahub/media/custom
|
||||
rm -rf $source_custom_dir
|
||||
mkdir -p ${seahub_data_dir}/custom
|
||||
ln -sf ${seahub_data_dir}/custom $source_custom_dir
|
||||
if [[ ! -e ${seahub_data_dir}/custom ]]; then
|
||||
mkdir -p ${seahub_data_dir}/custom
|
||||
fi
|
||||
rm -rf $source_custom_dir && ln -sf ${seahub_data_dir}/custom $source_custom_dir
|
||||
|
||||
rm -rf /var/lib/mysql
|
||||
if [[ ! -e /shared/db ]];then
|
||||
mkdir -p /shared/db
|
||||
fi
|
||||
ln -sf /shared/db /var/lib/mysql
|
||||
|
||||
if [[ ! -e /shared/logs/var-log ]]; then
|
||||
mv /var/log /shared/logs/var-log
|
||||
fi
|
||||
rm -rf /var/log && ln -sf /shared/logs/var-log /var/log
|
||||
|
|
|
@ -17,7 +17,7 @@ from utils import (
|
|||
call, get_conf, get_install_dir, loginfo,
|
||||
get_script, render_template, get_seafile_version, eprint,
|
||||
cert_has_valid_days, get_version_stamp_file, update_version_stamp,
|
||||
wait_for_mysql, wait_for_nginx
|
||||
wait_for_mysql, wait_for_nginx, read_version_stamp
|
||||
)
|
||||
|
||||
seafile_version = get_seafile_version()
|
||||
|
@ -34,7 +34,7 @@ def init_letsencrypt():
|
|||
if not exists(ssl_dir):
|
||||
os.mkdir(ssl_dir)
|
||||
|
||||
domain = get_conf('server.hostname')
|
||||
domain = get_conf('SEAFILE_SERVER_HOSTNAME', 'seafile.example.com')
|
||||
context = {
|
||||
'ssl_dir': ssl_dir,
|
||||
'domain': domain,
|
||||
|
@ -73,29 +73,20 @@ def init_letsencrypt():
|
|||
|
||||
def generate_local_nginx_conf():
|
||||
# Now create the final nginx configuratin
|
||||
domain = get_conf('server.hostname')
|
||||
domain = get_conf('SEAFILE_SERVER_HOSTNAME', 'seafile.example.com')
|
||||
context = {
|
||||
'https': is_https(),
|
||||
'domain': domain,
|
||||
}
|
||||
render_template(
|
||||
'/templates/seafile.nginx.conf.template',
|
||||
join(generated_dir, 'seafile.nginx.conf'),
|
||||
'/etc/nginx/sites-enabled/seafile.nginx.conf',
|
||||
context
|
||||
)
|
||||
|
||||
|
||||
def is_https():
|
||||
return get_conf('server.letsencrypt', '').lower() == 'true'
|
||||
|
||||
def generate_local_dockerfile():
|
||||
loginfo('Generating local Dockerfile ...')
|
||||
context = {
|
||||
'seafile_version': seafile_version,
|
||||
'https': is_https(),
|
||||
'domain': get_conf('server.domain'),
|
||||
}
|
||||
render_template('/templates/Dockerfile.template', join(generated_dir, 'Dockerfile'), context)
|
||||
return get_conf('SEAFILE_SERVER_LETSENCRYPT', 'false').lower() == 'true'
|
||||
|
||||
def parse_args():
|
||||
ap = argparse.ArgumentParser()
|
||||
|
@ -103,29 +94,23 @@ def parse_args():
|
|||
|
||||
return ap.parse_args()
|
||||
|
||||
def do_parse_ports():
|
||||
"""
|
||||
Parse the server.port_mappings option and print docker command line port
|
||||
mapping flags like "-p 80:80 -p 443:443"
|
||||
"""
|
||||
# conf is like '80:80,443:443'
|
||||
conf = get_conf('server.port_mappings', '').strip()
|
||||
if conf:
|
||||
sys.stdout.write(' '.join(['-p {}'.format(part.strip()) for part in conf.split(',')]))
|
||||
sys.stdout.flush()
|
||||
|
||||
def init_seafile_server():
|
||||
version_stamp_file = get_version_stamp_file()
|
||||
if exists(join(shared_seafiledir, 'seafile-data')):
|
||||
if not exists(version_stamp_file):
|
||||
update_version_stamp(os.environ['SEAFILE_VERSION'])
|
||||
# sysbol link unlink after docker finish.
|
||||
latest_version_dir='/opt/seafile/seafile-server-latest'
|
||||
current_version_dir='/opt/seafile/seafile-server-' + read_version_stamp()
|
||||
if not exists(latest_version_dir):
|
||||
call('ln -sf ' + current_version_dir + ' ' + latest_version_dir)
|
||||
loginfo('Skip running setup-seafile-mysql.py because there is existing seafile-data folder.')
|
||||
return
|
||||
|
||||
loginfo('Now running setup-seafile-mysql.py in auto mode.')
|
||||
env = {
|
||||
'SERVER_NAME': 'seafile',
|
||||
'SERVER_IP': get_conf('server.hostname'),
|
||||
'SERVER_IP': get_conf('SEAFILE_SERVER_HOSTNAME', 'seafile.example.com'),
|
||||
'MYSQL_USER': 'seafile',
|
||||
'MYSQL_USER_PASSWD': str(uuid.uuid4()),
|
||||
'MYSQL_USER_HOST': '127.0.0.1',
|
||||
|
@ -140,7 +125,7 @@ def init_seafile_server():
|
|||
setup_script = get_script('setup-seafile-mysql.sh')
|
||||
call('{} auto -n seafile'.format(setup_script), env=env)
|
||||
|
||||
domain = get_conf('server.hostname')
|
||||
domain = get_conf('SEAFILE_SERVER_HOSTNAME', 'seafile.example.com')
|
||||
proto = 'https' if is_https() else 'http'
|
||||
with open(join(topdir, 'conf', 'seahub_settings.py'), 'a+') as fp:
|
||||
fp.write('\n')
|
||||
|
@ -165,32 +150,7 @@ def init_seafile_server():
|
|||
dst = join(shared_seafiledir, fn)
|
||||
if not exists(dst) and exists(src):
|
||||
shutil.move(src, shared_seafiledir)
|
||||
call('ln -sf ' + join(shared_seafiledir, fn) + ' ' + src)
|
||||
|
||||
loginfo('Updating version stamp')
|
||||
update_version_stamp(os.environ['SEAFILE_VERSION'])
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
if args.parse_ports:
|
||||
do_parse_ports()
|
||||
return
|
||||
if not exists(shared_seafiledir):
|
||||
os.mkdir(shared_seafiledir)
|
||||
if not exists(generated_dir):
|
||||
os.mkdir(generated_dir)
|
||||
|
||||
generate_local_dockerfile()
|
||||
|
||||
if is_https():
|
||||
init_letsencrypt()
|
||||
generate_local_nginx_conf()
|
||||
|
||||
wait_for_mysql()
|
||||
init_seafile_server()
|
||||
|
||||
loginfo('Generated local config.')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# TODO: validate the content of bootstrap.conf is valid
|
||||
main()
|
|
@ -17,7 +17,13 @@ from utils import (
|
|||
call, get_conf, get_install_dir, get_script, get_command_output,
|
||||
render_template, wait_for_mysql
|
||||
)
|
||||
from upgrade import check_upgrade
|
||||
from bootstrap import init_seafile_server, is_https, init_letsencrypt, generate_local_nginx_conf
|
||||
|
||||
|
||||
shared_seafiledir = '/shared/seafile'
|
||||
ssl_dir = '/shared/ssl'
|
||||
generated_dir = '/bootstrap/generated'
|
||||
installdir = get_install_dir()
|
||||
topdir = dirname(installdir)
|
||||
|
||||
|
@ -36,15 +42,30 @@ def watch_controller():
|
|||
sys.exit(1)
|
||||
|
||||
def main():
|
||||
if not exists(shared_seafiledir):
|
||||
os.mkdir(shared_seafiledir)
|
||||
if not exists(generated_dir):
|
||||
os.makedirs(generated_dir)
|
||||
|
||||
if is_https():
|
||||
init_letsencrypt()
|
||||
generate_local_nginx_conf()
|
||||
call('nginx -s reload')
|
||||
|
||||
wait_for_mysql()
|
||||
init_seafile_server()
|
||||
|
||||
check_upgrade()
|
||||
os.chdir(installdir)
|
||||
|
||||
admin_pw = {
|
||||
'email': get_conf('admin.email'),
|
||||
'password': get_conf('admin.password'),
|
||||
'email': get_conf('SEAFILE_ADMIN_EMAIL', 'me@example.com'),
|
||||
'password': get_conf('SEAFILE_ADMIN_PASSWORD', 'asecret'),
|
||||
}
|
||||
password_file = join(topdir, 'conf', 'admin.txt')
|
||||
with open(password_file, 'w') as fp:
|
||||
json.dump(admin_pw, fp)
|
||||
|
||||
wait_for_mysql()
|
||||
|
||||
try:
|
||||
call('{} start'.format(get_script('seafile.sh')))
|
|
@ -218,12 +218,8 @@ def get_script(script):
|
|||
_config = None
|
||||
|
||||
def get_conf(key, default=None):
|
||||
global _config
|
||||
if _config is None:
|
||||
_config = ConfigParser()
|
||||
_config.read("/bootstrap/bootstrap.conf")
|
||||
return _config.get("server", key) if _config.has_option("server", key) \
|
||||
else default
|
||||
key = key.upper()
|
||||
return os.environ.get(key, default)
|
||||
|
||||
def _add_default_context(context):
|
||||
default_context = {
|
440
launcher
440
launcher
|
@ -1,432 +1,12 @@
|
|||
#!/bin/bash
|
||||
|
||||
usage () {
|
||||
echo "Usage: launcher COMMAND [--skip-prereqs] [--docker-args STRING]"
|
||||
echo "Commands:"
|
||||
echo " start: Start/initialize the container"
|
||||
echo " stop: Stop a running container"
|
||||
echo " restart: Restart the container"
|
||||
echo " destroy: Stop and remove the container"
|
||||
echo " enter: Open a shell to run commands inside the container"
|
||||
echo " logs: View the Docker container logs"
|
||||
echo " bootstrap: Bootstrap the container based on a template"
|
||||
echo " rebuild: Rebuild the container (destroy old, bootstrap, start new)"
|
||||
echo " gc: Start the seafile garbage collector (stops seafile, starts gc, restarts seafile)"
|
||||
echo
|
||||
echo "Options:"
|
||||
echo " --skip-prereqs Don't check launcher prerequisites"
|
||||
echo " --docker-args Extra arguments to pass when running docker"
|
||||
exit 1
|
||||
}
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
version=6.2.3
|
||||
image=seafileltd/seafile:$version
|
||||
local_image=local_seafile/server:latest
|
||||
dockerdir=$(cd "$(dirname $0)"; pwd -P)
|
||||
sharedir=$dockerdir/shared
|
||||
installdir=/opt/seafile/seafile-server-$version
|
||||
bootstrap_conf=$dockerdir/bootstrap/bootstrap.conf
|
||||
version_stamp_file=$sharedir/seafile/seafile-data/current_version
|
||||
|
||||
cd $dockerdir
|
||||
|
||||
logdbg() {
|
||||
if [[ $verbose == "true" ]]; then
|
||||
loginfo "[debug] $1"
|
||||
fi
|
||||
}
|
||||
|
||||
loginfo() {
|
||||
if [[ -t 1 ]]; then
|
||||
>&2 printf "[$(date +'%Y-%m-%d %H:%M:%S')] \033[32m%s\033[m\n" "$1"
|
||||
else
|
||||
>&2 echo "[$(date +'%Y-%m-%d %H:%M:%S')] " "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
install_docker() {
|
||||
echo "---------------------------------------------------------------------------------"
|
||||
echo "Docker is not installed, you will need to install Docker in order to run Launcher"
|
||||
echo "See https://docs.docker.com/installation/"
|
||||
echo "---------------------------------------------------------------------------------"
|
||||
exit 1
|
||||
}
|
||||
|
||||
err_and_quit () {
|
||||
if [[ -t 1 ]]; then
|
||||
>&2 printf "\n\n\033[33mError: %s\033[m\n\n" "$1"
|
||||
else
|
||||
>&2 echo "$1"
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
init_shared() {
|
||||
mkdir -p $sharedir/{seafile,db}
|
||||
mkdir -p $sharedir/logs/{seafile,var-log}
|
||||
|
||||
mkdir -p $sharedir/logs/var-log/nginx
|
||||
touch $sharedir/logs/var-log/syslog
|
||||
|
||||
local bash_history=$sharedir/.bash_history
|
||||
if [[ ! -e $bash_history ]]; then
|
||||
touch $bash_history
|
||||
fi
|
||||
}
|
||||
|
||||
set_envs() {
|
||||
envs=""
|
||||
if [[ $verbose == "true" ]]; then
|
||||
envs="$envs -e SEAFILE_DOCKER_VERBOSE=true"
|
||||
fi
|
||||
}
|
||||
|
||||
set_ports() {
|
||||
ports=$(docker run $user_args --rm -it \
|
||||
-v ${dockerdir}/scripts:/scripts \
|
||||
-v ${dockerdir}/bootstrap:/bootstrap:ro \
|
||||
$image \
|
||||
/scripts/bootstrap.py --parse-ports)
|
||||
}
|
||||
|
||||
set_bootstrap_volumes() {
|
||||
local mounts
|
||||
init_shared
|
||||
|
||||
mounts=(
|
||||
$sharedir:/shared
|
||||
$sharedir/logs/var-log:/var/log
|
||||
$sharedir/db:/var/lib/mysql
|
||||
$dockerdir/bootstrap:/bootstrap
|
||||
$dockerdir/scripts:/scripts:ro
|
||||
$dockerdir/templates:/templates:ro
|
||||
$dockerdir/scripts/tmp/check_init_admin.py:$installdir/check_init_admin.py:ro
|
||||
$sharedir/.bash_history:/root/.bash_history
|
||||
)
|
||||
volumes=""
|
||||
local m
|
||||
for m in ${mounts[*]}; do
|
||||
volumes="$volumes -v $m"
|
||||
done
|
||||
}
|
||||
|
||||
set_volumes() {
|
||||
local mounts
|
||||
init_shared
|
||||
|
||||
mounts=(
|
||||
$sharedir:/shared
|
||||
$sharedir/logs/var-log:/var/log
|
||||
$sharedir/db:/var/lib/mysql
|
||||
$sharedir/.bash_history:/root/.bash_history
|
||||
)
|
||||
volumes=""
|
||||
local m
|
||||
for m in ${mounts[*]}; do
|
||||
volumes="$volumes -v $m"
|
||||
done
|
||||
}
|
||||
|
||||
set_existing_container() {
|
||||
existing=$(docker ps -a | awk '{ print $1, $(NF) }' | grep " seafile$" | awk '{ print $1 }' || true)
|
||||
}
|
||||
|
||||
bootstrap() {
|
||||
if [[ ! -e $bootstrap_conf ]]; then
|
||||
err_and_quit "The file $bootstrap_conf doesn't exist. Have you run seafile-server-setup?"
|
||||
fi
|
||||
|
||||
docker history $image >/dev/null 2>&1 || {
|
||||
loginfo "Pulling Seafile server image $version, this may take a while."
|
||||
docker pull $image
|
||||
loginfo "Seafile server image $version pulled. Now bootstrapping the server ..."
|
||||
}
|
||||
|
||||
# First initialize seafile server and letsencrypt
|
||||
set_envs
|
||||
set_bootstrap_volumes
|
||||
set_ports
|
||||
|
||||
docker run $user_args --rm -it --name seafile-bootstrap -e SEAFILE_BOOTSRAP=1 $envs $volumes $ports $image /sbin/my_init $quiet -- /scripts/bootstrap.py
|
||||
|
||||
loginfo "Now building the local docker image."
|
||||
docker build -f bootstrap/generated/Dockerfile -t local_seafile/server:latest . >/dev/null
|
||||
loginfo "Image built."
|
||||
}
|
||||
|
||||
start() {
|
||||
existing=$(docker ps | awk '{ print $1, $(NF) }' | grep " seafile$" | awk '{ print $1 }' || true)
|
||||
if [[ $existing != "" ]]; then
|
||||
loginfo "Nothing to do, your container has already started!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
check_version_match
|
||||
|
||||
chmod 0700 $dockerdir/bootstrap $sharedir/seafile/conf
|
||||
|
||||
set_existing_container
|
||||
if [[ $existing != "" ]]; then
|
||||
loginfo "starting up existing container"
|
||||
(
|
||||
set -x
|
||||
docker start seafile
|
||||
)
|
||||
exit 0
|
||||
fi
|
||||
|
||||
set_envs
|
||||
set_volumes
|
||||
set_ports
|
||||
|
||||
local restart_policy attach_on_run
|
||||
if [[ "${SUPERVISED}" = "true" ]]; then
|
||||
restart_policy="--restart=no"
|
||||
attach_on_run="-a stdout -a stderr"
|
||||
else
|
||||
attach_on_run="-d"
|
||||
fi
|
||||
|
||||
loginfo "Starting up new seafile server container"
|
||||
(
|
||||
set -x
|
||||
docker run $user_args $attach_on_run $restart_policy --name seafile -h seafile $envs $volumes $ports $local_image
|
||||
)
|
||||
}
|
||||
|
||||
ensure_container_running() {
|
||||
set_existing_container
|
||||
if [[ $existing == "" ]]; then
|
||||
err_and_quit "seafile was not started !"
|
||||
fi
|
||||
}
|
||||
|
||||
stop() {
|
||||
ensure_container_running
|
||||
(
|
||||
set -x
|
||||
docker stop -t 10 seafile
|
||||
)
|
||||
}
|
||||
|
||||
enter() {
|
||||
ensure_container_running
|
||||
(
|
||||
set -x
|
||||
docker exec -it seafile /bin/bash
|
||||
)
|
||||
}
|
||||
|
||||
restart() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
gc() {
|
||||
ensure_container_running
|
||||
(
|
||||
loginfo "Stop seafile and start the garbage collector"
|
||||
set +e +x
|
||||
docker exec -it seafile /scripts/gc.sh
|
||||
gc_error=$?
|
||||
if [[ $gc_error -eq 0 ]]; then
|
||||
loginfo "Garbage collector finished!"
|
||||
else
|
||||
err_and_quit "Garbage collector exited with code $gc_error"
|
||||
fi
|
||||
)
|
||||
}
|
||||
|
||||
check_prereqs() {
|
||||
if [[ $SKIP_PREREQS == "true" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# check docker
|
||||
if ! which docker >/dev/null; then
|
||||
install_docker
|
||||
fi
|
||||
# TODO: check git version
|
||||
}
|
||||
|
||||
logs() {
|
||||
ensure_container_running
|
||||
(
|
||||
set -x
|
||||
docker logs --tail=20 -f seafile
|
||||
)
|
||||
}
|
||||
|
||||
destroy() {
|
||||
(
|
||||
set -x
|
||||
docker stop -t 10 seafile || true
|
||||
docker rm seafile
|
||||
)
|
||||
}
|
||||
|
||||
get_major_version() {
|
||||
echo $1| awk -F . '{printf "%s.%s", $1, $2}'
|
||||
}
|
||||
|
||||
check_version_match() {
|
||||
local last_version last_major_version current_major_version
|
||||
last_version=$(cat $version_stamp_file)
|
||||
last_major_version=$(get_major_version $last_version)
|
||||
current_major_version=$(get_major_version $version)
|
||||
|
||||
logdbg "Your version: ${last_version}, latest version: ${version}"
|
||||
|
||||
if [[ $last_major_version != "$current_major_version" ]]; then
|
||||
loginfo "******* Major upgrade detected *******"
|
||||
loginfo "You have $last_version, latest is $version"
|
||||
loginfo "Please run './launcher rebuild' to upgrade"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_upgrade() {
|
||||
loginfo "Checking if there is major version upgrade"
|
||||
|
||||
local last_version last_major_version current_major_version
|
||||
last_version=$(cat $version_stamp_file)
|
||||
last_major_version=$(get_major_version $last_version)
|
||||
current_major_version=$(get_major_version $version)
|
||||
|
||||
if [[ $last_major_version == "$current_major_version" ]]; then
|
||||
return
|
||||
else
|
||||
loginfo "********************************"
|
||||
loginfo "Major upgrade detected: You have $last_version, latest is $version"
|
||||
loginfo "********************************"
|
||||
|
||||
# use_manual_upgrade=true
|
||||
if [[ $use_manual_upgrade == "true" ]]; then
|
||||
loginfo "Now you can run './launcher manual-upgrade' to do manual upgrade."
|
||||
exit 0
|
||||
else
|
||||
loginfo "Going to launch the docker container for manual upgrade"
|
||||
_launch_for_upgrade --auto
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_launch_for_upgrade() {
|
||||
local cmd
|
||||
if [[ $1 == "--auto" ]]; then
|
||||
cmd="/scripts/upgrade.py"
|
||||
else
|
||||
cmd="/bin/bash"
|
||||
fi
|
||||
|
||||
set_envs
|
||||
set_volumes
|
||||
(
|
||||
set -x
|
||||
docker run $user_args \
|
||||
-it --rm --name seafile-upgrade -h seafile \
|
||||
$envs $volumes $local_image \
|
||||
/sbin/my_init $quiet -- $cmd
|
||||
)
|
||||
}
|
||||
|
||||
rebuild() {
|
||||
if [[ "$(git symbolic-ref --short HEAD)" == "master" ]]; then
|
||||
loginfo "Ensuring launcher is up to date"
|
||||
|
||||
git remote update
|
||||
|
||||
LOCAL=$(git rev-parse @)
|
||||
REMOTE=$(git rev-parse "@{u}")
|
||||
BASE=$(git merge-base @ "@{u}")
|
||||
|
||||
if [[ $LOCAL = "$REMOTE" ]]; then
|
||||
loginfo "Launcher is up-to-date"
|
||||
|
||||
elif [[ $LOCAL = "$BASE" ]]; then
|
||||
loginfo "Updating Launcher"
|
||||
git pull || (echo 'failed to update' && exit 1)
|
||||
|
||||
for (( i=${#BASH_ARGV[@]}-1,j=0; i>=0,j<${#BASH_ARGV[@]}; i--,j++ ))
|
||||
do
|
||||
args[$j]=${BASH_ARGV[$i]}
|
||||
done
|
||||
exec /bin/bash $0 "${args[@]}" # $@ is empty, because of shift at the beginning. Use BASH_ARGV instead.
|
||||
|
||||
elif [[ $REMOTE = "$BASE" ]]; then
|
||||
loginfo "Your version of Launcher is ahead of origin"
|
||||
else
|
||||
loginfo "Launcher has diverged source, this is only expected in Dev mode"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
set_existing_container
|
||||
|
||||
if [[ $existing != "" ]]; then
|
||||
loginfo "Stopping old container"
|
||||
(
|
||||
set -x
|
||||
docker stop -t 10 seafile
|
||||
)
|
||||
fi
|
||||
|
||||
bootstrap
|
||||
loginfo "Rebuilt successfully."
|
||||
|
||||
if [[ $existing != "" ]]; then
|
||||
loginfo "Removing old container"
|
||||
(
|
||||
set -x
|
||||
docker rm seafile
|
||||
)
|
||||
fi
|
||||
|
||||
check_upgrade
|
||||
|
||||
start
|
||||
|
||||
loginfo "Your seafile server is now running."
|
||||
exit 0
|
||||
}
|
||||
|
||||
manual_upgrade() {
|
||||
_launch_for_upgrade
|
||||
loginfo "If you have manually upgraded the server, please update the version stamp by:"
|
||||
loginfo
|
||||
loginfo " echo $version | sudo tee $version_stamp_file"
|
||||
loginfo " sudo ./launcher start"
|
||||
loginfo
|
||||
}
|
||||
|
||||
main() {
|
||||
local action
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
case "$1" in
|
||||
bootstrap|start|stop|restart|enter|destroy|logs|rebuild|manual-upgrade|gc)
|
||||
action=${1//-/_} ; shift 1 ;;
|
||||
-h|--help) ( usage ; exit 1) ; shift 1 ;;
|
||||
-v|--verbose) verbose=true ; shift 1 ;;
|
||||
--skip-prereqs) SKIP_PREREQS=true ; shift 1 ;;
|
||||
--docker-args) user_args=$2 ; shift 2 ;;
|
||||
--manual-upgrade) use_manual_upgrade=true ; shift 1 ;;
|
||||
*) err_and_quit "Argument error. Please see help." ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# By default we suppress the verbose logs like "Running
|
||||
# /etc/my_init.d/99_mysql_setup.sh". Use "./launcher -v <cmd>" to enable
|
||||
# printing of these verbose logs.
|
||||
quiet="--quiet"
|
||||
if [[ $verbose == "true" ]]; then
|
||||
quiet=""
|
||||
fi
|
||||
"$action"
|
||||
}
|
||||
|
||||
check_prereqs
|
||||
main "$@"
|
||||
echo "================================================================================================================================="
|
||||
echo "The launcher script is now deprecated. Please see https://github.com/haiwen/seafile-docker/blob/master/upgrade_from_old_format.md"
|
||||
echo "================================================================================================================================="
|
||||
echo
|
||||
echo "Or run this command directly:"
|
||||
echo
|
||||
echo " docker rm -f seafile"
|
||||
echo " docker run -d -it --name seafile -v $(dirname $PWD)/shared:/shared -p 80:80 -p 443:443 seafileltd/server"
|
||||
echo
|
||||
echo "================================================================================================================================="
|
||||
|
|
602
launcher.ps1
602
launcher.ps1
|
@ -1,602 +0,0 @@
|
|||
# -*- buffer-file-coding-system: utf-8-unix -*-
|
||||
<#
|
||||
|
||||
This is the powershell version of the launcher script to be used on windows.
|
||||
you should use it instead of the linux 'launcher' script.
|
||||
|
||||
#>
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$version = "6.2.3"
|
||||
$image = "seafileltd/seafile:$version"
|
||||
$local_image = "local_seafile/server:latest"
|
||||
|
||||
$dockerdir = $PSScriptRoot.Replace("\", "/")
|
||||
$sharedir = "$dockerdir/shared"
|
||||
$installdir = "/opt/seafile/seafile-server-$version"
|
||||
|
||||
$bootstrap_conf="$dockerdir/bootstrap/bootstrap.conf"
|
||||
$version_stamp_file="$sharedir/seafile/seafile-data/current_version"
|
||||
$bash_history="$sharedir/.bash_history"
|
||||
|
||||
function usage() {
|
||||
Write-Host "Usage: launcher.ps1 COMMAND [-skipPrereqs]"
|
||||
Write-Host "Commands:"
|
||||
Write-Host " start: Start/initialize the container"
|
||||
Write-Host " stop: Stop a running container"
|
||||
Write-Host " restart: Restart the container"
|
||||
Write-Host " destroy: Stop and remove the container"
|
||||
Write-Host " enter: Open a shell to run commands inside the container"
|
||||
Write-Host " logs: View the Docker container logs"
|
||||
Write-Host " bootstrap: Bootstrap the container based on a template"
|
||||
Write-Host " rebuild: Rebuild the container (destroy old, bootstrap, start new)"
|
||||
Write-Host ""
|
||||
Write-Host "Options:"
|
||||
Write-Host " -skipPrereqs Don't check launcher prerequisites"
|
||||
exit 1
|
||||
}
|
||||
|
||||
function main() {
|
||||
Param(
|
||||
[Parameter(Position=1)]
|
||||
[string]$action,
|
||||
|
||||
[switch]$skipPrereqs,
|
||||
|
||||
[switch]$v
|
||||
)
|
||||
|
||||
$script:action = $action
|
||||
$script:skipPrereqs = $skipPrereqs
|
||||
# Always verbose before we reach a stable release.
|
||||
$script:v = $true
|
||||
$script:verbose = $script:v
|
||||
|
||||
check_is_system_supported
|
||||
|
||||
if (!$action) {
|
||||
usage
|
||||
}
|
||||
|
||||
# loginfo "action = $action"
|
||||
if (!$skipPrereqs) {
|
||||
check_prereqs
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
"bootstrap" { do_bootstrap }
|
||||
"start" { do_start }
|
||||
"stop" { do_stop }
|
||||
"restart" { do_restart }
|
||||
"enter" { do_enter }
|
||||
"destroy" { do_destroy }
|
||||
"logs" { do_logs }
|
||||
"rebuild" { do_rebuild }
|
||||
"manual-upgrade" { do_manual_upgrade }
|
||||
default { usage }
|
||||
}
|
||||
}
|
||||
|
||||
<# A Powershell version of the following bash code:
|
||||
|
||||
[[ $a == "1" ]] || {
|
||||
# do something else when a != 1
|
||||
}
|
||||
|
||||
Use it like:
|
||||
|
||||
do_if_not { where.exe docker } { loginfo "docker program doesn't exist"}
|
||||
|
||||
Currently the first branch must be a subprocess call.
|
||||
|
||||
#>
|
||||
function do_if_not([scriptblock]$block_1, [scriptblock]$block_2) {
|
||||
$failed = $false
|
||||
$global:LASTEXITCODE = $null
|
||||
try {
|
||||
& $block_1
|
||||
} catch [System.Management.Automation.RemoteException] {
|
||||
$failed = $true
|
||||
}
|
||||
if ($failed -or !($global:LASTEXITCODE -eq 0)) {
|
||||
& $block_2
|
||||
}
|
||||
}
|
||||
|
||||
function do_if([scriptblock]$block_1, [scriptblock]$block_2) {
|
||||
$failed = $false
|
||||
$global:LASTEXITCODE = $null
|
||||
try {
|
||||
& $block_1
|
||||
} catch [System.Management.Automation.RemoteException] {
|
||||
$failed = $true
|
||||
}
|
||||
if (!($failed) -and ($global:LASTEXITCODE -eq 0)) {
|
||||
& $block_2
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
Mimics python's `subproess.check_output`: Run the given command, capture the
|
||||
output, and terminate the script if the command fails. For example:
|
||||
|
||||
check_output docker run ...
|
||||
|
||||
Code borrowed from http://stackoverflow.com/a/11549817/1467959
|
||||
#>
|
||||
function check_output($cmd) {
|
||||
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
|
||||
$pinfo.FileName = $cmd
|
||||
$pinfo.RedirectStandardError = $false
|
||||
$pinfo.RedirectStandardOutput = $true
|
||||
$pinfo.UseShellExecute = $false
|
||||
$pinfo.WorkingDirectory = $PSScriptRoot
|
||||
if ($args) {
|
||||
$pinfo.Arguments = $args
|
||||
}
|
||||
$p = New-Object System.Diagnostics.Process
|
||||
$p.StartInfo = $pinfo
|
||||
$p.Start() | Out-Null
|
||||
$stdout = $p.StandardOutput.ReadToEnd()
|
||||
$p.WaitForExit()
|
||||
echo "$stdout"
|
||||
if (!($p.ExitCode -eq 0)) {
|
||||
err_and_quit "The command $cmd $args failed"
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
|
||||
Mimics python's `subprocess.check_call`: Run the given command, capture the
|
||||
output, and terminate the script if the command fails. For example:
|
||||
|
||||
check_call docker run ...
|
||||
|
||||
#>
|
||||
function check_call($cmd) {
|
||||
if ($args) {
|
||||
$process = Start-Process -NoNewWindow -Wait -FilePath "$cmd" -ArgumentList $args -PassThru
|
||||
} else {
|
||||
$process = Start-Process -NoNewWindow -Wait -FilePath "$cmd" -PassThru
|
||||
}
|
||||
if (!($process.ExitCode -eq 0)) {
|
||||
if ($script:on_call_error) {
|
||||
err_and_quit $script:on_call_error
|
||||
$script:on_call_error = $null
|
||||
} else {
|
||||
err_and_quit "The command $cmd $args failed with code $LASTEXITCODE"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function get_date_str() {
|
||||
Get-Date -format "yyyy-MM-dd hh:mm:ss"
|
||||
}
|
||||
|
||||
function err_and_quit($msg) {
|
||||
Write-Host -BackgroundColor Black -ForegroundColor Yellow -Object "[$(get_date_str)] Error: $msg"
|
||||
exit 1
|
||||
}
|
||||
|
||||
function logdbg($msg) {
|
||||
if ($script:verbose) {
|
||||
loginfo "[debug] $msg"
|
||||
}
|
||||
}
|
||||
|
||||
function loginfo($msg) {
|
||||
Write-Host -ForegroundColor Green -Object "[$(get_date_str)] $msg"
|
||||
}
|
||||
|
||||
function program_exists($exe) {
|
||||
try {
|
||||
Get-Command "$exe" -CommandType Application 2>&1>$null
|
||||
} catch [CommandNotFoundException] {
|
||||
}
|
||||
return $?
|
||||
}
|
||||
|
||||
function to_unix_path($path) {
|
||||
$path -replace '^|\\+','/' -replace ':'
|
||||
}
|
||||
|
||||
$sharedir_u = $(to_unix_path $sharedir)
|
||||
$dockerdir_u = $(to_unix_path $dockerdir)
|
||||
|
||||
function check_prereqs() {
|
||||
if (!(program_exists "git.exe")) {
|
||||
err_and_quit "You need to install git first. Check https://git-scm.com/download/win".
|
||||
}
|
||||
|
||||
if (!(program_exists "docker.exe")) {
|
||||
err_and_quit "You need to install docker first. Check https://docs.docker.com/docker-for-windows/."
|
||||
}
|
||||
}
|
||||
|
||||
function check_is_system_supported() {
|
||||
$ver = [Environment]::OSVersion
|
||||
if (!($ver.Version.Major -eq 10)) {
|
||||
err_and_quit "Only Windows 10 is supported."
|
||||
}
|
||||
}
|
||||
|
||||
function set_envs() {
|
||||
$script:envs = @()
|
||||
if ($script:v) {
|
||||
$script:envs += "-e"
|
||||
$script:envs += "SEAFILE_DOCKER_VERBOSE=true"
|
||||
}
|
||||
}
|
||||
|
||||
# Call powershell mkdir, but only create the directory when it doesn't exist
|
||||
function makedir($path) {
|
||||
if (!(Test-Path $path)) {
|
||||
New-Item -ItemType "Directory" -Force -Path $path 2>&1>$null
|
||||
}
|
||||
}
|
||||
|
||||
function touch($path) {
|
||||
if (!(Test-Path $path)) {
|
||||
New-Item -ItemType "file" -Path $path 2>&1>$null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function init_shared() {
|
||||
makedir "$sharedir/seafile"
|
||||
makedir "$sharedir/db"
|
||||
makedir "$sharedir/logs/seafile"
|
||||
makedir "$sharedir/logs/var-log"
|
||||
|
||||
makedir "$sharedir/logs/var-log/nginx"
|
||||
touch "$sharedir/logs/var-log/syslog"
|
||||
touch $bash_history
|
||||
}
|
||||
|
||||
function set_bootstrap_volumes() {
|
||||
init_shared
|
||||
|
||||
$mounts = @(
|
||||
"${sharedir_u}:/shared",
|
||||
"${sharedir_u}/logs/var-log:/var/log",
|
||||
"${sharedir_u}/db:/var/lib/mysql",
|
||||
"${dockerdir_u}/bootstrap:/bootstrap",
|
||||
"${dockerdir_u}/scripts:/scripts:ro",
|
||||
"${dockerdir_u}/templates:/templates:ro",
|
||||
"${dockerdir_u}/scripts/tmp/check_init_admin.py:$installdir/check_init_admin.py:ro",
|
||||
"${sharedir_u}/.bash_history:/root/.bash_history"
|
||||
)
|
||||
$script:volumes = @()
|
||||
foreach($m in $mounts) {
|
||||
$script:volumes += "-v"
|
||||
$script:volumes += "$m"
|
||||
}
|
||||
}
|
||||
|
||||
function set_volumes() {
|
||||
init_shared
|
||||
|
||||
$mounts = @(
|
||||
"${sharedir_u}:/shared",
|
||||
"${sharedir_u}/logs/var-log:/var/log",
|
||||
"${sharedir_u}/db:/var/lib/mysql",
|
||||
"${sharedir_u}/.bash_history:/root/.bash_history"
|
||||
)
|
||||
$script:volumes=@()
|
||||
foreach($m in $mounts) {
|
||||
$script:volumes += "-v"
|
||||
$script:volumes += "$m"
|
||||
}
|
||||
}
|
||||
|
||||
function set_ports() {
|
||||
$ports = $(check_output "docker" "run" "--rm" "-it" `
|
||||
"-v" "${dockerdir_u}/scripts:/scripts" `
|
||||
"-v" "${dockerdir_u}/bootstrap:/bootstrap:ro" `
|
||||
$image `
|
||||
"/scripts/bootstrap.py" "--parse-ports")
|
||||
|
||||
# The output is like "-p 80:80 -p 443:443", we need to split it into an array
|
||||
$script:ports = $(-split $ports)
|
||||
}
|
||||
|
||||
function set_my_init() {
|
||||
$script:my_init = @("/sbin/my_init")
|
||||
if (!($script:v)) {
|
||||
$script:my_init += "--quiet"
|
||||
}
|
||||
}
|
||||
|
||||
function parse_seafile_container([array]$lines) {
|
||||
foreach($line in $lines) {
|
||||
$fields = $(-split $line)
|
||||
if ("seafile".Equals($fields[-1])) {
|
||||
echo $fields[0]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
## We can write it using more elegant "ForEach-Object" using the following
|
||||
## code, but someone says that "break" works like "continue" in the
|
||||
## ForEach-Object's script block.
|
||||
##
|
||||
## See ## http://stackoverflow.com/a/7763698/1467959
|
||||
##
|
||||
## Anway, we use a foreach loop to keep the code
|
||||
## simple.
|
||||
##
|
||||
# $lines | ForEach-Object {
|
||||
# $fields =$(-split $_)
|
||||
# if ("seafile".Equals($fields[-1])) {
|
||||
# echo $fields[0]
|
||||
# break
|
||||
# }
|
||||
# }
|
||||
}
|
||||
|
||||
# Equivalent of `docker ps | awk '{ print $1, $(NF) }' | grep " seafile$" | awk '{ print $1 }' || true`
|
||||
function set_running_container() {
|
||||
try {
|
||||
$script:existing = $(parse_seafile_container $(check_output docker ps))
|
||||
} catch [System.Management.Automation.RemoteException] {
|
||||
$script:existing = ""
|
||||
}
|
||||
}
|
||||
|
||||
# Equivalent of `docker ps -a |awk '{ print $1, $(NF) }' | grep " seafile$" | awk '{ print $1 }' || true`
|
||||
function set_existing_container() {
|
||||
try {
|
||||
$script:existing = $(parse_seafile_container $(docker ps -a))
|
||||
} catch [System.Management.Automation.RemoteException] {
|
||||
$script:existing = ""
|
||||
}
|
||||
}
|
||||
|
||||
function ensure_container_running() {
|
||||
set_existing_container
|
||||
if (!($script:existing)) {
|
||||
err_and_quit "seafile was not started !"
|
||||
}
|
||||
}
|
||||
|
||||
function ignore_error($cmd) {
|
||||
if ($args) {
|
||||
Start-Process -NoNewWindow -Wait -FilePath "$cmd" -ArgumentList $args
|
||||
} else {
|
||||
Start-Process -NoNewWindow -Wait -FilePath "$cmd"
|
||||
}
|
||||
}
|
||||
|
||||
function remove_container($container) {
|
||||
do_if { docker inspect $container 2>&1>$null } {
|
||||
docker rm -f $container 2>&1>$null
|
||||
}
|
||||
}
|
||||
|
||||
function do_bootstrap() {
|
||||
if (!(Test-Path $bootstrap_conf)) {
|
||||
err_and_quit "The file $bootstrap_conf doesn't exist. Have you run seafile-server-setup?"
|
||||
}
|
||||
|
||||
do_if_not { docker history $image 2>&1>$null } {
|
||||
loginfo "Pulling Seafile server image $version, this may take a while."
|
||||
check_call docker pull $image
|
||||
loginfo "Seafile server image $version pulled. Now bootstrapping the server ..."
|
||||
}
|
||||
|
||||
set_envs
|
||||
set_bootstrap_volumes
|
||||
set_ports
|
||||
set_my_init
|
||||
|
||||
# loginfo "ports is $script:ports"
|
||||
remove_container "seafile-bootstrap"
|
||||
|
||||
check_call "docker" "run" "--rm" "-it" "--name" "seafile-bootstrap" `
|
||||
"-e" "SEAFILE_BOOTSRAP=1" `
|
||||
@script:envs `
|
||||
@script:volumes `
|
||||
@script:ports `
|
||||
$image `
|
||||
@script:my_init "--" "/scripts/bootstrap.py"
|
||||
# @script:my_init "--" "/bin/bash"
|
||||
|
||||
loginfo "Now building the local docker image."
|
||||
check_call "docker" "build" "-f" "bootstrap/generated/Dockerfile" "-t" "local_seafile/server:latest" "." 2>$null
|
||||
loginfo "Image built."
|
||||
}
|
||||
|
||||
function do_start() {
|
||||
set_running_container
|
||||
if ($script:running) {
|
||||
loginfo "Nothing to do, your container has already started!"
|
||||
exit 0
|
||||
}
|
||||
|
||||
check_version_match
|
||||
|
||||
set_existing_container
|
||||
if ($script:existing) {
|
||||
loginfo "starting up existing container"
|
||||
check_call docker start seafile
|
||||
exit 0
|
||||
}
|
||||
|
||||
set_envs
|
||||
set_volumes
|
||||
set_ports
|
||||
|
||||
$attach_on_run = @()
|
||||
$restart_policy = @()
|
||||
if ("true".Equals($SUPERVISED)) {
|
||||
$restart_policy = @("--restart=no")
|
||||
$attach_on_run = @("-a", "stdout", "-a", "stderr")
|
||||
} else {
|
||||
$attach_on_run = @("-d")
|
||||
}
|
||||
|
||||
loginfo "Starting up new seafile server container"
|
||||
remove_container "seafile"
|
||||
docker run @attach_on_run @restart_policy --name seafile -h seafile @envs @volumes @ports $local_image
|
||||
}
|
||||
|
||||
function do_rebuild() {
|
||||
$branch=(check_output git symbolic-ref --short HEAD).Trim()
|
||||
if ("master".Equals($branch)) {
|
||||
loginfo "Ensuring launcher is up to date"
|
||||
|
||||
check_call git remote update
|
||||
|
||||
$LOCAL=(check_output git rev-parse "@").Trim()
|
||||
$REMOTE=(check_output git rev-parse "@{u}").Trim()
|
||||
$BASE=(check_output git merge-base "@" "@{u}").Trim()
|
||||
|
||||
if ($LOCAL.Equals($REMOTE)) {
|
||||
loginfo "Launcher is up-to-date"
|
||||
|
||||
} elseif ($LOCAL.Equals($BASE)) {
|
||||
loginfo "Updating Launcher"
|
||||
do_if_not { git pull } {
|
||||
err_and_quit "failed to update"
|
||||
}
|
||||
|
||||
$myself = Join-Path $PSScriptRoot $script:MyInvocation.MyCommand
|
||||
$newargs = @($myself) + $script:args
|
||||
# logdbg "Running: Start-Process -NoNewWindow -FilePath powershell.exe -ArgumentList $($newargs)"
|
||||
Start-Process -NoNewWindow -FilePath powershell.exe -ArgumentList $newargs -Wait
|
||||
exit 0
|
||||
|
||||
} elseif ($REMOTE.Equals($BASE)) {
|
||||
loginfo "Your version of Launcher is ahead of origin"
|
||||
|
||||
} else {
|
||||
loginfo "Launcher has diverged source, this is only expected in Dev mode"
|
||||
}
|
||||
}
|
||||
|
||||
set_existing_container
|
||||
|
||||
if ($script:existing) {
|
||||
loginfo "Stopping old container"
|
||||
check_call docker stop -t 10 seafile
|
||||
}
|
||||
|
||||
do_bootstrap
|
||||
loginfo "Rebuilt successfully."
|
||||
|
||||
if ($script:existing) {
|
||||
loginfo "Removing old container"
|
||||
check_call docker rm seafile
|
||||
}
|
||||
|
||||
check_upgrade
|
||||
|
||||
do_start
|
||||
|
||||
loginfo "Your seafile server is now running."
|
||||
}
|
||||
|
||||
function get_major_version($ver) {
|
||||
echo "$($ver.Split(".")[0..1] -join ".")"
|
||||
}
|
||||
|
||||
function check_version_match() {
|
||||
$last_version=(Get-Content $version_stamp_file).Trim()
|
||||
$last_major_version=$(get_major_version $last_version)
|
||||
$current_major_version=$(get_major_version $version)
|
||||
|
||||
logdbg "Your version: ${last_version}, latest version: ${version}"
|
||||
|
||||
if (!($last_major_version.Equals($current_major_version))) {
|
||||
loginfo "******* Major upgrade detected *******"
|
||||
loginfo "You have $last_version, latest is $version"
|
||||
loginfo "Please run './launcher.ps1 rebuild' to upgrade"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
function check_upgrade() {
|
||||
loginfo "Checking if there is major version upgrade"
|
||||
|
||||
$last_version=(Get-Content $version_stamp_file).Trim()
|
||||
$last_major_version=$(get_major_version $last_version)
|
||||
$current_major_version=$(get_major_version $version)
|
||||
|
||||
if ($last_major_version.Equals($current_major_version)) {
|
||||
return
|
||||
} else {
|
||||
loginfo "********************************"
|
||||
loginfo "Major upgrade detected: You have $last_version, latest is $version"
|
||||
loginfo "********************************"
|
||||
|
||||
# $use_manual_upgrade="true"
|
||||
if ("true".Equals($use_manual_upgrade)) {
|
||||
loginfo "Now you can run './launcher.ps1 manual-upgrade' to do manual upgrade."
|
||||
exit 0
|
||||
} else {
|
||||
loginfo "Going to launch the docker container for manual upgrade"
|
||||
_launch_for_upgrade -auto
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _launch_for_upgrade([switch]$auto) {
|
||||
if ($auto) {
|
||||
$script:on_call_error = 'Failed to upgrade to latest version. You can try run it manually by "./launcher.ps1 manual-upgrade"'
|
||||
$cmd="/scripts/upgrade.py"
|
||||
} else {
|
||||
$script:on_call_error = "Upgrade failed"
|
||||
$cmd="/bin/bash"
|
||||
}
|
||||
|
||||
set_envs
|
||||
set_volumes
|
||||
|
||||
remove_container seafile-upgrade
|
||||
|
||||
check_call docker run `
|
||||
-it -rm --name seafile-upgrade -h seafile `
|
||||
@script:envs @script:volumes $local_image `
|
||||
@script:my_init -- $cmd
|
||||
}
|
||||
|
||||
function do_manual_upgrade() {
|
||||
_launch_for_upgrade
|
||||
|
||||
loginfo "If you have manually upgraded the server, please update the version stamp by:"
|
||||
loginfo
|
||||
loginfo " Set-Content -Path ""$version_stamp_file"" -Value $version"
|
||||
loginfo " ./launcher.ps1 start"
|
||||
loginfo
|
||||
}
|
||||
|
||||
function do_stop() {
|
||||
ensure_container_running
|
||||
loginfo "Stopping seafile container"
|
||||
check_call docker stop -t 10 seafile
|
||||
}
|
||||
|
||||
function do_restart() {
|
||||
do_stop
|
||||
do_start
|
||||
}
|
||||
|
||||
function do_enter() {
|
||||
ensure_container_running
|
||||
loginfo "Launching a linux bash shell in the seafile container"
|
||||
docker exec -it seafile /bin/bash
|
||||
}
|
||||
|
||||
function do_destroy() {
|
||||
loginfo "Stopping seafile container"
|
||||
ignore_error docker stop -t 10 seafile
|
||||
ignore_error docker rm seafile
|
||||
}
|
||||
|
||||
function do_logs() {
|
||||
ensure_container_running
|
||||
docker logs --tail=20 -f seafile
|
||||
}
|
||||
|
||||
main @args
|
|
@ -6,4 +6,3 @@ admin.email = me@example.com
|
|||
admin.password = asecret
|
||||
|
||||
server.letsencrypt = true
|
||||
server.port_mappings = 80:80,443:443
|
|
@ -4,7 +4,5 @@ server.hostname = seafile.example.com
|
|||
admin.email = me@example.com
|
||||
admin.password = asecret
|
||||
|
||||
# Comment out this line and uncomment the two lines below to use letsencrypt SSL certificate
|
||||
server.port_mappings = 80:80
|
||||
# uncomment the one lines below to use letsencrypt SSL certificate
|
||||
# server.letsencrypt = true
|
||||
# server.port_mappings = 80:80,443:443
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
err_and_quit () {
|
||||
printf "\n\n\033[33mError occured during setup. \nPlease fix possible issues and run the script again.\033[m\n\n"
|
||||
exit 1
|
||||
}
|
||||
|
||||
on_ctrl_c_pressed () {
|
||||
printf "\n\n\033[33mYou have pressed Ctrl-C. Setup is interrupted.\033[m\n\n"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# clean newly created ccnet/seafile configs when exit on SIGINT
|
||||
trap on_ctrl_c_pressed 2
|
||||
|
||||
read_yes_no () {
|
||||
printf "[yes|no] "
|
||||
read yesno
|
||||
while [[ "$yesno" != "yes" && "$yesno" != "no" ]]
|
||||
do
|
||||
printf "please answer [yes|no] "
|
||||
read yesno
|
||||
done
|
||||
|
||||
if [[ "$yesno" == "no" ]]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
ask_question () {
|
||||
local question default key
|
||||
question=$1
|
||||
default=$2
|
||||
key=$3
|
||||
printf "$question"
|
||||
printf "\n"
|
||||
if [[ "$default" != "" && "$default" != "nodefault" ]]; then
|
||||
printf "[default: $default] "
|
||||
elif [[ "$key" != "" ]]; then
|
||||
printf "[$key]: "
|
||||
fi
|
||||
}
|
||||
|
||||
get_server_name () {
|
||||
local question="Host name for your seafile server?" default="seafile.example.com"
|
||||
ask_question "$question" "seafile.example.com"
|
||||
read server_name
|
||||
if [[ "$server_name" == "" ]]; then
|
||||
server_name=$default
|
||||
elif [[ ! $server_name =~ ^[a-zA-Z0-9_-.]+$ ]]; then
|
||||
printf "\n\033[33m${server_name}\033[m is not a valid name.\n"
|
||||
get_server_name
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
# echo "Please specify the email address and password for the seahub administrator."
|
||||
# echo "You can use them to login as admin on your seahub website."
|
||||
# echo
|
||||
|
||||
get_admin_email () {
|
||||
local question="Admin email address for your seafile server?" default="me@example.com"
|
||||
ask_question "$question" "$default"
|
||||
read admin_email
|
||||
if [[ "$admin_email" == "" ]]; then
|
||||
admin_email=$default
|
||||
elif [[ ! $admin_email =~ ^.+@.*\..+$ ]]; then
|
||||
echo "$admin_email is not a valid email address"
|
||||
get_admin_email
|
||||
fi
|
||||
}
|
||||
|
||||
get_admin_passwd () {
|
||||
local question="Admin password for your seafile server?"
|
||||
ask_question "$question" "nodefault" "seahub admin password"
|
||||
read -s admin_passwd
|
||||
echo
|
||||
question="Please enter the password again:"
|
||||
ask_question "$question" "nodefault" "seahub admin password again"
|
||||
read -s admin_passwd_again
|
||||
echo
|
||||
if [[ "$admin_passwd" != "$admin_passwd_again" ]]; then
|
||||
printf "\033[33mThe passwords didn't match.\033[m"
|
||||
get_admin_passwd
|
||||
elif [[ "$admin_passwd" == "" ]]; then
|
||||
echo "Password cannot be empty."
|
||||
get_admin_passwd
|
||||
fi
|
||||
}
|
||||
|
||||
get_server_name
|
||||
get_admin_email
|
||||
get_admin_passwd
|
||||
|
||||
cat >bootstrap/bootstrap.conf<<EOF
|
||||
[server]
|
||||
server.hostname = $server_name
|
||||
admin.email = $admin_email
|
||||
admin.password = $admin_passwd
|
||||
EOF
|
||||
|
||||
./launcher bootstrap && ./launcher start
|
21
upgrade_from_old_format.md
Normal file
21
upgrade_from_old_format.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
Follow these steps:
|
||||
|
||||
1. Stop the old container.
|
||||
2. Delete the old container.
|
||||
3. Delete the old images.
|
||||
4. Clone the latest docker project.
|
||||
5. Build the new images.
|
||||
6. Run the new container.
|
||||
|
||||
e.g.
|
||||
|
||||
Assume your old project path is /opt/seafile-docker, so your data path is /opt/seafile-docker/shared.
|
||||
|
||||
docker stop seafile
|
||||
docker rm seafile
|
||||
docker rmi $(image id)
|
||||
git cloen https://github.com/haiwen/seafile-docker.git
|
||||
cd images && make base && make server
|
||||
docker run -it --name seafile -v /opt/seafile-docker/shared:/shared -p 80:80 -p 443:443 seafileltd/seafile:6.2.3
|
||||
|
||||
Congratulations, you've upgraded to a new version.
|
Loading…
Reference in a new issue