fix(docker): add dockfile and small fixes (#38)
* fix(docker): add dockfile and small fixes * chore(readme): small fixes
This commit is contained in:
parent
c8a3f911e8
commit
b0d1cdccfc
11 changed files with 126 additions and 36 deletions
16
Dockerfile
Normal file
16
Dockerfile
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
FROM golang:1.15 as build-be
|
||||||
|
ADD . /quickshare
|
||||||
|
WORKDIR /quickshare
|
||||||
|
RUN /quickshare/scripts/build_be_docker.sh
|
||||||
|
|
||||||
|
FROM node as build-fe
|
||||||
|
COPY --from=build-be /quickshare /quickshare
|
||||||
|
WORKDIR /quickshare
|
||||||
|
RUN yarn install \
|
||||||
|
&& yarn --cwd "src/client/web" run build \
|
||||||
|
&& cp -R /quickshare/public /quickshare/dist/quickshare
|
||||||
|
|
||||||
|
FROM gcr.io/distroless/base-debian10
|
||||||
|
COPY --from=build-fe /quickshare/dist/quickshare /quickshare
|
||||||
|
ADD configs/docker.yml /quickshare
|
||||||
|
CMD ["/quickshare/start", "-c", "/quickshare/docker.yml"]
|
47
README.md
47
README.md
|
@ -2,7 +2,7 @@
|
||||||
Quickshare
|
Quickshare
|
||||||
</h1>
|
</h1>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Simple file sharing service built with Go/Golang, Typescript, Gin, React, Boltdb, etc.
|
Quick and simple file sharing between different devices.
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/ihexxa/quickshare/actions">
|
<a href="https://github.com/ihexxa/quickshare/actions">
|
||||||
|
@ -24,26 +24,55 @@ Choose Language: English | [简体中文](./docs/README_zh-cn.md)
|
||||||
|
|
||||||
## Main Features
|
## Main Features
|
||||||
|
|
||||||
- Sharing files among different devices (Adaptive UI)
|
- Sharing and accessing from different devices (Adaptive UI)
|
||||||
- Be compatible with Linux, Mac and Windows
|
- Be compatible with Linux, Mac and Windows
|
||||||
- Stopping and resuming uploading/downloading
|
- Stopping and resuming uploading/downloading
|
||||||
- Do uploading and downloading in web browser
|
- Do uploading and downloading in web browser
|
||||||
|
- Manage files in browser or in OS
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
**Downloading**: Download last distribution(s) in [Release Page](https://github.com/ihexxa/quickshare/releases).
|
### Run in Docker
|
||||||
|
|
||||||
**Unzipping**: Unzip it and run following command `./quickshare`. (You may update its execution permission: e.g. run `chmod u+x quickshare` on Linux)
|
Following will start a `quickshare` docker and listen to `8686` port.
|
||||||
|
|
||||||
**Starting**: At the first run, Quickshare will let you input your user name and generate a random password for you (here `quickshare` is the user name). It may output something like following (password is `2fdc98`):
|
Then you can open `http://127.0.0.1:8686` and log in with user name `qs` and password `1234`:
|
||||||
|
|
||||||
```
|
```
|
||||||
Please input admin name: quickshare
|
docker run \
|
||||||
password is generated: 2fdc98, please update it after login
|
--name quickshare \
|
||||||
user (quickshare) is created
|
-d -p :8686:8686 \
|
||||||
|
-v `pwd`/quickshare/root:/quickshare/root \
|
||||||
|
-e DEFAULTADMIN=qs \
|
||||||
|
-e DEFAULTADMINPWD=1234 \
|
||||||
|
hexxa/quickshare:0.3.0
|
||||||
```
|
```
|
||||||
|
|
||||||
**Accessing**: At last, open your browser and visit `http://127.0.0.1:8686`.
|
- `DEFAULTADMIN` is the default user name
|
||||||
|
- `DEFAULTADMINPWD` is the default user password
|
||||||
|
- `/quickshare/root` is where Quickshare stores files and directories.
|
||||||
|
|
||||||
|
### Run from source code
|
||||||
|
|
||||||
|
Before start, please ensure Go/Golang (>1.15), Node.js and Yarn are installed on your machine.
|
||||||
|
|
||||||
|
```
|
||||||
|
# clone this repo
|
||||||
|
git clone git@github.com:ihexxa/quickshare.git
|
||||||
|
|
||||||
|
# go to repo's folder
|
||||||
|
cd quickshare
|
||||||
|
|
||||||
|
DEFAULTADMIN=qs DEFAULTADMINPWD=1234 yarn start
|
||||||
|
```
|
||||||
|
|
||||||
|
OK! Open `http://127.0.0.1:8686` in browser, and log in with user name `qs` and password `1234`.
|
||||||
|
|
||||||
|
### Run executable file
|
||||||
|
|
||||||
|
- **Downloading**: Download last distribution(s) in [Release Page](https://github.com/ihexxa/quickshare/releases).
|
||||||
|
- **Unzipping**: Unzip it and run following command `DEFAULTADMIN=qs DEFAULTADMINPWD=1234 ./quickshare`. (You may update its execution permission: e.g. run `chmod u+x quickshare`)
|
||||||
|
- **Accessing**: At last, open `http://127.0.0.1:8686` in browser, and log in with user name `qs` and password `1234`.
|
||||||
|
|
||||||
### FAQ
|
### FAQ
|
||||||
|
|
||||||
|
|
|
@ -31,11 +31,14 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(opts.Configs) > 0 {
|
if len(opts.Configs) > 0 {
|
||||||
for _, configPath := range opts.Configs {
|
for _, configPath := range opts.Configs {
|
||||||
if strings.HasSuffix(configPath, ".yml") || strings.HasSuffix(configPath, ".yaml") {
|
if strings.HasSuffix(configPath, ".yml") || strings.HasSuffix(configPath, ".yaml") {
|
||||||
|
fmt.Printf("launching config: %s\n", configPath)
|
||||||
cfg, err = cfg.Load(gocfg.YAML(configPath))
|
cfg, err = cfg.Load(gocfg.YAML(configPath))
|
||||||
} else if strings.HasSuffix(configPath, ".json") {
|
} else if strings.HasSuffix(configPath, ".json") {
|
||||||
|
fmt.Printf("launching config: %s\n", configPath)
|
||||||
cfg, err = cfg.Load(gocfg.JSON(configPath))
|
cfg, err = cfg.Load(gocfg.JSON(configPath))
|
||||||
} else {
|
} else {
|
||||||
panic(fmt.Sprintf("unknown config file type (.yml .yaml .json are supported): %s", configPath))
|
panic(fmt.Sprintf("unknown config file type (.yml .yaml .json are supported): %s", configPath))
|
||||||
|
@ -62,6 +65,7 @@ func main() {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("quickshare is listening %d\n", cfg.GrabInt("Server.Port"))
|
||||||
err = srv.Start()
|
err = srv.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
21
configs/docker.yml
Normal file
21
configs/docker.yml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
fs:
|
||||||
|
root: "/quickshare/root"
|
||||||
|
opensLimit: 128
|
||||||
|
openTTL: 60 # 1 min
|
||||||
|
secrets:
|
||||||
|
tokenSecret: ""
|
||||||
|
server:
|
||||||
|
debug: false
|
||||||
|
host: "0.0.0.0"
|
||||||
|
port: 8686
|
||||||
|
readTimeout: 2000
|
||||||
|
writerTimeout: 86400000 # 1 day
|
||||||
|
maxHeaderBytes: 512
|
||||||
|
publicPath: "/quickshare/public"
|
||||||
|
users:
|
||||||
|
enableAuth: true
|
||||||
|
defaultAdmin: ""
|
||||||
|
defaultAdminPwd: ""
|
||||||
|
cookieTTL: 604800 # 1 week
|
||||||
|
cookieSecure: false
|
||||||
|
cookieHttpOnly: true
|
|
@ -4,7 +4,7 @@
|
||||||
"src/client/web"
|
"src/client/web"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "scripts/build",
|
"build": "scripts/build.sh",
|
||||||
"start": "go run cmd/start/main.go -c `pwd`/configs/dev.yml"
|
"start": "cd src/client/web/ && yarn && yarn build && cd ../../.. && go run cmd/start/main.go -c `pwd`/configs/dev.yml"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
scripts/build_be_docker.sh
Executable file
11
scripts/build_be_docker.sh
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
export QSROOT=`pwd`
|
||||||
|
rm -r dist && mkdir dist
|
||||||
|
|
||||||
|
# set this for builders behind GFW...
|
||||||
|
go env -w GOPROXY=https://goproxy.cn,direct
|
||||||
|
go get -d -v ./...
|
||||||
|
go get github.com/mitchellh/gox
|
||||||
|
cd cmd/start
|
||||||
|
gox \
|
||||||
|
-osarch="linux/amd64" \
|
||||||
|
-output "$QSROOT/dist/quickshare/start"
|
7
scripts/docker_run.sh
Normal file
7
scripts/docker_run.sh
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
docker run \
|
||||||
|
--name quickshare \
|
||||||
|
-d -p :8686:8686 \
|
||||||
|
-v `pwd`/quickshare/root:/quickshare/root \
|
||||||
|
-e DEFAULTADMIN=qs \
|
||||||
|
-e DEFAULTADMINPWD=1234 \
|
||||||
|
hexxa/quickshare:0.3.0
|
|
@ -4,7 +4,8 @@
|
||||||
"description": "web client for quickshare",
|
"description": "web client for quickshare",
|
||||||
"main": "",
|
"main": "",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn prod:addjs && webpack --config webpack.app.prod.js",
|
"build": "yarn prod:addjs && yarn build:prod:wp",
|
||||||
|
"build:prod:wp": "webpack --config webpack.app.prod.js",
|
||||||
"build:watch": "webpack --config webpack.app.prod.js --watch",
|
"build:watch": "webpack --config webpack.app.prod.js --watch",
|
||||||
"build:dev": "yarn dev:addjs && webpack --config webpack.app.dev.js --watch",
|
"build:dev": "yarn dev:addjs && webpack --config webpack.app.dev.js --watch",
|
||||||
"test": "jest test --maxWorkers=2",
|
"test": "jest test --maxWorkers=2",
|
||||||
|
|
|
@ -46,6 +46,7 @@ type FileHandlers struct {
|
||||||
|
|
||||||
func NewFileHandlers(cfg gocfg.ICfg, deps *depidx.Deps) (*FileHandlers, error) {
|
func NewFileHandlers(cfg gocfg.ICfg, deps *depidx.Deps) (*FileHandlers, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if err = deps.FS().MkdirAll(UploadDir); err != nil {
|
if err = deps.FS().MkdirAll(UploadDir); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -113,7 +114,7 @@ func (h *FileHandlers) Create(c *gin.Context) {
|
||||||
}
|
}
|
||||||
userName := c.MustGet(singleuserhdr.UserParam).(string)
|
userName := c.MustGet(singleuserhdr.UserParam).(string)
|
||||||
|
|
||||||
tmpFilePath := getTmpPath(req.Path)
|
tmpFilePath := h.getTmpPath(req.Path)
|
||||||
locker := h.NewAutoLocker(c, lockName(userName, tmpFilePath))
|
locker := h.NewAutoLocker(c, lockName(userName, tmpFilePath))
|
||||||
locker.Exec(func() {
|
locker.Exec(func() {
|
||||||
err := h.deps.FS().Create(tmpFilePath)
|
err := h.deps.FS().Create(tmpFilePath)
|
||||||
|
@ -261,7 +262,7 @@ func (h *FileHandlers) UploadChunk(c *gin.Context) {
|
||||||
}
|
}
|
||||||
userName := c.MustGet(singleuserhdr.UserParam).(string)
|
userName := c.MustGet(singleuserhdr.UserParam).(string)
|
||||||
|
|
||||||
tmpFilePath := getTmpPath(req.Path)
|
tmpFilePath := h.getTmpPath(req.Path)
|
||||||
locker := h.NewAutoLocker(c, lockName(userName, tmpFilePath))
|
locker := h.NewAutoLocker(c, lockName(userName, tmpFilePath))
|
||||||
locker.Exec(func() {
|
locker.Exec(func() {
|
||||||
var err error
|
var err error
|
||||||
|
@ -331,7 +332,7 @@ func (h *FileHandlers) UploadStatus(c *gin.Context) {
|
||||||
}
|
}
|
||||||
userName := c.MustGet(singleuserhdr.UserParam).(string)
|
userName := c.MustGet(singleuserhdr.UserParam).(string)
|
||||||
|
|
||||||
tmpFilePath := getTmpPath(filePath)
|
tmpFilePath := h.getTmpPath(filePath)
|
||||||
locker := h.NewAutoLocker(c, lockName(userName, tmpFilePath))
|
locker := h.NewAutoLocker(c, lockName(userName, tmpFilePath))
|
||||||
locker.Exec(func() {
|
locker.Exec(func() {
|
||||||
_, fileSize, uploaded, err := h.uploadMgr.GetInfo(userName, tmpFilePath)
|
_, fileSize, uploaded, err := h.uploadMgr.GetInfo(userName, tmpFilePath)
|
||||||
|
@ -468,7 +469,7 @@ func (h *FileHandlers) CopyDir(c *gin.Context) {
|
||||||
c.JSON(q.NewMsgResp(501, "Not Implemented"))
|
c.JSON(q.NewMsgResp(501, "Not Implemented"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTmpPath(filePath string) string {
|
func (h *FileHandlers) getTmpPath(filePath string) string {
|
||||||
return path.Join(UploadDir, fmt.Sprintf("%x", sha1.Sum([]byte(filePath))))
|
return path.Join(UploadDir, fmt.Sprintf("%x", sha1.Sum([]byte(filePath))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,7 +505,7 @@ func (h *FileHandlers) DelUploading(c *gin.Context) {
|
||||||
userName := c.MustGet(singleuserhdr.UserParam).(string)
|
userName := c.MustGet(singleuserhdr.UserParam).(string)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
tmpFilePath := getTmpPath(filePath)
|
tmpFilePath := h.getTmpPath(filePath)
|
||||||
locker := h.NewAutoLocker(c, lockName(userName, tmpFilePath))
|
locker := h.NewAutoLocker(c, lockName(userName, tmpFilePath))
|
||||||
locker.Exec(func() {
|
locker.Exec(func() {
|
||||||
err = h.deps.FS().Remove(tmpFilePath)
|
err = h.deps.FS().Remove(tmpFilePath)
|
||||||
|
|
|
@ -9,33 +9,33 @@ type FSConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type UsersCfg struct {
|
type UsersCfg struct {
|
||||||
EnableAuth bool `json:"enableAuth"`
|
EnableAuth bool `json:"enableAuth" yaml:"enableAuth"`
|
||||||
DefaultAdmin string `json:"defaultAdmin" cfg:"env"`
|
DefaultAdmin string `json:"defaultAdmin" yaml:"defaultAdmin" cfg:"env"`
|
||||||
DefaultAdminPwd string `json:"defaultAdminPwd" cfg:"env"`
|
DefaultAdminPwd string `json:"defaultAdminPwd" yaml:"defaultAdminPwd" cfg:"env"`
|
||||||
CookieTTL int `json:"cookieTTL"`
|
CookieTTL int `json:"cookieTTL" yaml:"cookieTTL"`
|
||||||
CookieSecure bool `json:"cookieSecure"`
|
CookieSecure bool `json:"cookieSecure" yaml:"cookieSecure"`
|
||||||
CookieHttpOnly bool `json:"cookieHttpOnly"`
|
CookieHttpOnly bool `json:"cookieHttpOnly" yaml:"cookieHttpOnly"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Secrets struct {
|
type Secrets struct {
|
||||||
TokenSecret string `json:"tokenSecret" cfg:"env"`
|
TokenSecret string `json:"tokenSecret" yaml:"tokenSecret" cfg:"env"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerCfg struct {
|
type ServerCfg struct {
|
||||||
Debug bool `json:"debug"`
|
Debug bool `json:"debug" yaml:"debug"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host" yaml:"host"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port" yaml:"port"`
|
||||||
ReadTimeout int `json:"readTimeout"`
|
ReadTimeout int `json:"readTimeout" yaml:"readTimeout"`
|
||||||
WriteTimeout int `json:"writeTimeout"`
|
WriteTimeout int `json:"writeTimeout" yaml:"writeTimeout"`
|
||||||
MaxHeaderBytes int `json:"maxHeaderBytes"`
|
MaxHeaderBytes int `json:"maxHeaderBytes" yaml:"maxHeaderBytes"`
|
||||||
PublicPath string `json:"publicPath"`
|
PublicPath string `json:"publicPath" yaml:"publicPath"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Fs *FSConfig `json:"fs"`
|
Fs *FSConfig `json:"fs" yaml:"fs"`
|
||||||
Secrets *Secrets `json:"secrets"`
|
Secrets *Secrets `json:"secrets" yaml:"secrets"`
|
||||||
Server *ServerCfg `json:"server"`
|
Server *ServerCfg `json:"server" yaml:"server"`
|
||||||
Users *UsersCfg `json:"users"`
|
Users *UsersCfg `json:"users" yaml:"users"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfig() *Config {
|
func NewConfig() *Config {
|
||||||
|
@ -45,7 +45,7 @@ func NewConfig() *Config {
|
||||||
func DefaultConfig() (string, error) {
|
func DefaultConfig() (string, error) {
|
||||||
defaultCfg := &Config{
|
defaultCfg := &Config{
|
||||||
Fs: &FSConfig{
|
Fs: &FSConfig{
|
||||||
Root: ".",
|
Root: "root",
|
||||||
OpensLimit: 128,
|
OpensLimit: 128,
|
||||||
OpenTTL: 60, // 1 min
|
OpenTTL: 60, // 1 min
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue