diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..8841fdb7dd96359c21d95378a0309b98deeda193
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,30 @@
+# block everything
+**
+
+# allowed files
+!AGPL-3
+!CHANGELOG.md
+!README.md
+!README.png
+!.babelrc
+!.eslintignore
+!.eslintrc.js
+!.postcssrc.js
+!favicon.ico
+!index.html
+!package.json
+!yarn.lock
+
+# allowed subdirectories
+!/build/**
+!/config/**
+!/docker/**
+!/public/**
+!/static/**
+!/src/**
+
+# blocked subdirectory files
+**/*.log
+**/*~
+**/.DS_Store
+**/Thumbs.db
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index cef4ec5ccdc1e0b70efc0642bdb7b6dfc26a4f5f..5542e7f4baae4b6710890bc67c3f10d7516aaa1b 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,26 +1,97 @@
-image: node:10
+image: node:10-alpine
+
+variables: &global_variables
+  DOCKER_DRIVER: overlay2
+  DOCKER_HOST: unix:///var/run/docker.sock
+
+cache: &global_cache_policy
+  key: '$CI_COMMIT_SHORT_SHA'
+  policy: pull-push
+  paths:
+    - node_modules/
+    - build
 
 stages:
-  - lint
   - build
   - test
+  - release
 
-lint:
-  stage: lint
+build:
+  stage: build
+  before_script: &before-build
+    - apk --no-cache add git
   script:
+    - npm install
+    - npm run build:prod
+  artifacts: &release-artifacts
+    name: "admin-fe-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA"
+    paths:
+      - dist/
+
+lint:
+  stage: test
+  before_script: &before-yarn
+    - apk --no-cache add git
+    - yarn cache clean
     - yarn
+  cache:
+    key: '$CI_COMMIT_SHORT_SHA'
+    policy: pull
+  script:
     - yarn lint
 
 test:
   stage: test
-  variables:
-    APT_CACHE_DIR: apt-cache
+  before_script: *before-yarn
+  cache:
+    key: '$CI_COMMIT_SHORT_SHA'
+    policy: pull
   script:
-    - yarn
     - yarn test
 
-build:
-  stage: build
+docker:
+  stage: release
+  image: docker:latest
+  cache: {}
+  dependencies: []
+  variables: &docker-variables
+    IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
+    IMAGE_TAG_SLUG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+    IMAGE_TAG_LATEST: $CI_REGISTRY_IMAGE:latest
+    IMAGE_TAG_LATEST_STABLE: $CI_REGISTRY_IMAGE:stable
+  before_script: &before-docker
+    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+    - docker pull $IMAGE_TAG_SLUG || true
+    - export CI_JOB_TIMESTAMP=$(date --utc -Iseconds)
+    - export CI_VCS_REF=$CI_COMMIT_SHORT_SHA
+  allow_failure: true
   script:
-    - yarn
-    - npm run build:prod
+    - docker build --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST .
+    - docker push $IMAGE_TAG
+    - docker push $IMAGE_TAG_SLUG
+    - docker push $IMAGE_TAG_LATEST
+  tags:
+    - dind
+  only:
+    - develop@pleroma/admin-fe
+    - /^(features|ci)\/.*/@jp/admin-fe
+
+docker-stable:
+  stage: release
+  image: docker:latest
+  cache: {}
+  dependencies: []
+  variables: *docker-variables
+  before_script: *before-docker
+  allow_failure: true
+  script:
+    - docker build --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST_STABLE .
+    - docker push $IMAGE_TAG
+    - docker push $IMAGE_TAG_SLUG
+    - docker push $IMAGE_TAG_LATEST_STABLE
+  tags:
+    - dind
+  only:
+    - master@pleroma/admin-fe
+
+
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..fef057d9bf990bd2e45156f49ce0ffef01c8a22e
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,38 @@
+FROM node:10-alpine as build
+
+COPY . .
+
+RUN apk --no-cache add git && \
+    npm install && \
+    npm run build:prod
+
+FROM nginx:mainline-alpine
+
+LABEL maintainer="ops@pleroma.social" \
+    org.opencontainers.image.title="pleroma-adminfe" \
+    org.opencontainers.image.description="Pleroma-adminfe for Docker" \
+    org.opencontainers.image.authors="ops@pleroma.social" \
+    org.opencontainers.image.vendor="pleroma.social" \
+    org.opencontainers.image.documentation="https://git.pleroma.social/pleroma/pleroma-adminfe" \
+    org.opencontainers.image.licenses="AGPL-3.0" \
+    org.opencontainers.image.url="https://pleroma.social" \
+    org.opencontainers.image.revision=$VCS_REF \
+    org.opencontainers.image.created=$BUILD_DATE
+
+
+ARG DATA=/usr/share/nginx/html
+
+COPY --from=build /dist/ ${DATA}
+
+COPY ./docker/docker-entrypoint.sh /usr/local/bin/
+
+COPY ./docker/nginx.conf.tpl /etc/nginx/nginx.conf.tpl
+
+RUN apk add --no-cache gettext
+
+EXPOSE 80
+
+ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
+
+CMD exec nginx -g 'daemon off;'
+
diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh
new file mode 100755
index 0000000000000000000000000000000000000000..eaf84fe020f5fbe5afa9936680b41ebeb25dbf8b
--- /dev/null
+++ b/docker/docker-entrypoint.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+set -e
+envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < "/etc/nginx/nginx.conf.tpl" > "/etc/nginx/nginx.conf"
+exec "$@"
diff --git a/docker/nginx.conf.tpl b/docker/nginx.conf.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..0f16dafafc209fa45510923eeddcb17ebd064867
--- /dev/null
+++ b/docker/nginx.conf.tpl
@@ -0,0 +1,32 @@
+user  nginx;
+worker_processes  1;
+error_log  /var/log/nginx/error.log warn;
+pid        /tmp/nginx.pid;
+events {
+    worker_connections  1024;
+}
+http {
+    client_body_temp_path /tmp/client_temp;
+    proxy_temp_path       /tmp/proxy_temp_path;
+    fastcgi_temp_path     /tmp/fastcgi_temp;
+    uwsgi_temp_path       /tmp/uwsgi_temp;
+    scgi_temp_path        /tmp/scgi_temp;
+    include       /etc/nginx/mime.types;
+    default_type  application/octet-stream;
+    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+                      '$status $body_bytes_sent "$http_referer" '
+                      '"$http_user_agent" "$http_x_forwarded_for"';
+    access_log  /var/log/nginx/access.log  main;
+    sendfile        on;
+    keepalive_timeout  65;
+    proxy_cache_path /tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g
+                     inactive=720m use_temp_path=off;
+    server {
+        listen 80;
+        server_name _;
+        root /usr/share/nginx/html;
+        location / {
+        try_files $uri $uri/ /index.html;
+      }
+    }
+}
diff --git a/src/lang/en.js b/src/lang/en.js
index 272dc4b048f764ebea44d4a87a42353f697b24b4..24c1a3b9553a8b625a7eed777c87e0e73a97b10f 100644
--- a/src/lang/en.js
+++ b/src/lang/en.js
@@ -358,7 +358,8 @@ export default {
     successfullyUpdated: 'Successfully updated',
     metadatLowerCase: 'metadata',
     files: 'files',
-    successfullyRemoved: 'Setting removed successfully!'
+    successfullyRemoved: 'Setting removed successfully!',
+    seeDocs: 'See Documentation'
   },
   invites: {
     inviteTokens: 'Invite tokens',
diff --git a/src/views/settings/components/Inputs.vue b/src/views/settings/components/Inputs.vue
index 35e29aae4b8567503543de0f5c44e468951d44b1..0ee369619d0cb7fb00afc169d92fddbd97407b18 100644
--- a/src/views/settings/components/Inputs.vue
+++ b/src/views/settings/components/Inputs.vue
@@ -46,7 +46,7 @@
         :size="isDesktop ? 'large' : 'small'"
         @change="update($event, settingGroup.group, settingGroup.key, settingParent, setting.key, setting.type, nested)"/>
       <el-select
-        v-if="setting.type === 'module' || (setting.type.includes('atom') && setting.type.includes(false))"
+        v-if="setting.type === 'module' || (setting.type.includes('atom') && setting.type.includes('dropdown'))"
         :value="inputValue"
         clearable
         @change="update($event, settingGroup.group, settingGroup.key, settingParent, setting.key, setting.type, nested)">
diff --git a/src/views/settings/components/Logger.vue b/src/views/settings/components/Logger.vue
index ff4ab6b2b9f43d3751175fe914df0ffd7b7d2d42..08fe4d81c117430473b43ed7330fc913a716c4d2 100644
--- a/src/views/settings/components/Logger.vue
+++ b/src/views/settings/components/Logger.vue
@@ -13,7 +13,6 @@
     </el-form>
     <div class="line"/>
     <el-form ref="quackData" :model="quackData" :label-width="labelWidth">
-      <el-form-item label="Quack logger:" class="settings-input"/>
       <setting :setting-group="quack" :data="quackData"/>
     </el-form>
     <div class="submit-button-container">
diff --git a/src/views/settings/index.vue b/src/views/settings/index.vue
index 2e77f905cd2e08f3fec4b8f18cf8ffbb2bd0ccfc..a78db3babcd474e1545faeb88a319a403b7d3a93 100644
--- a/src/views/settings/index.vue
+++ b/src/views/settings/index.vue
@@ -1,6 +1,19 @@
 <template>
   <div class="settings-container">
-    <h1 class="settings-header">{{ $t('settings.settings') }}</h1>
+    <div class="settings-header-container">
+      <h1 class="settings-header">{{ $t('settings.settings') }}</h1>
+      <el-link
+        :underline="false"
+        href="https://docs-develop.pleroma.social/backend/admin/config/"
+        target="_blank">
+        <el-button class="settings-docs-button">
+          <span>
+            <i class="el-icon-document"/>
+            {{ $t('settings.seeDocs') }}
+          </span>
+        </el-button>
+      </el-link>
+    </div>
     <el-tabs v-if="isDesktop" v-model="activeTab" tab-position="left">
       <el-tab-pane :label="$t('settings.activityPub')" :disabled="configDisabled" name="activityPub" lazy>
         <activity-pub/>
@@ -187,9 +200,6 @@ export default {
     },
     isMobile() {
       return this.$store.state.app.device === 'mobile'
-    },
-    tabPosition() {
-      return this.isMobile ? 'top' : 'left'
     }
   },
   mounted: function() {
@@ -203,11 +213,23 @@ export default {
   .el-tabs {
     margin-top: 20px
   }
-
+}
+.settings-docs-button {
+  width: 163px;
+  text-align: left;
+  padding: 10px;
 }
 .settings-header {
-  margin: 22px 0 0 15px;
+  margin: 0;
+}
+.settings-header-container {
+  display: flex;
+  height: 36px;
+  justify-content: space-between;
+  align-items: center;
+  margin: 22px 30px 15px 15px;
 }
+
 @media only screen and (min-width: 1824px) {
   .settings-container {
     max-width: 1824px;
diff --git a/src/views/statuses/index.vue b/src/views/statuses/index.vue
index df120bc7ae944b2d72c8cb83e735738b93990ae1..828526c84c949ec46fbf8255e9d7fa6255ca98e4 100644
--- a/src/views/statuses/index.vue
+++ b/src/views/statuses/index.vue
@@ -112,11 +112,11 @@ export default {
   }
 }
 .filter-container {
-    display: flex;
-    height: 36px;
-    justify-content: space-between;
-    align-items: center;
-    margin: 22px 0 15px 0;
+  display: flex;
+  height: 36px;
+  justify-content: space-between;
+  align-items: center;
+  margin: 22px 0 15px 0;
 }
 .select-instance {
   width: 350px;