├── .gitignore ├── README.md ├── docker-compose.yml └── docker-nginx ├── Dockerfile ├── LICENSE.md ├── README.md ├── docker-entrypoint.sh └── nginx.conf /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea 3 | /docker-codescene/resources/caacs_enterprise.db.mv.db 4 | /docker-codescene/codescene/codescene.log 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodeScene on Docker 2 | 3 | ## Note: this is only an example how to run CodeScene behind an nginx proxy server. The image in the docker-codescene/ directory isn't maintained and you should use https://hub.docker.com/r/empear/codescene instead 4 | 5 | This repository is an example of how to run CodeScene in a Docker 6 | instance behind an nginx reverse proxy. Even if you are not using Docker, the 7 | nginx configuration may be helpful for running CodeScene behind nginx. 8 | 9 | `docker-compose` is used here to run two Docker containers, one running 10 | nginx, the other with CodeScene itself. The [CodeScene 11 | docker image](https://hub.docker.com/r/empear/ubuntu-onprem) can also be used by itself to 12 | run CodeScene directly. 13 | 14 | ## Install 15 | 16 | This assumes that you have a working Docker installation. 17 | 18 | Clone this repository and go to the top level directory. 19 | 20 | git clone git@github.com:empear-analytics/docker-codescene-nginx-self-signed-ssl.git 21 | cd docker-codescene-nginx-self-signed-ssl 22 | 23 | ### Prepare the host and reverse proxy configuration for Letsencrypt SSL certificate 24 | 25 | Install certbot on the host according to the instructions found here: https://certbot.eff.org/lets-encrypt/ubuntubionic-other 26 | Replace `**domain_name**` with your correct domain name in docker-nginx/nginx.conf 27 | 28 | The complete code is available in the `using_letsecrypt_ssl` branch - see https://github.com/empear-analytics/docker-codescene-nginx-self-signed-ssl/commit/1db5245b40b10ee954e3b23261f40b6e29a4b665. 29 | 30 | ## Build 31 | 32 | The reverse proxy using Nginx is built like this: 33 | 34 | docker build -t reverseproxy docker-nginx/ 35 | 36 | The CodeScene image is available from [Docker Hub](https://hub.docker.com/r/empear/ubuntu-onprem/). 37 | 38 | If you want to use a specific version of CodeScene, you can add a tag in the `docker-compose.yml`: 39 | 40 | ``` 41 | image: empear/ubuntu-onprem:latest 42 | ``` 43 | 44 | ## Run 45 | 46 | ### Run CodeScene behind the reverse proxy 47 | 48 | Use `docker-compose` to start both instances: 49 | 50 | docker-compose up -d 51 | 52 | ### Run CodeScene by itself without the reverse proxy: 53 | 54 | docker pull empear/ubuntu-onprem 55 | docker run -i -t -p 3003 \ 56 | --name myname \ 57 | --mount type=bind,source=$PWD/docker-codescene/codescene,destination=/codescene \ 58 | empear/ubuntu-onprem 59 | 60 | To connect to this instance: 61 | 62 | docker exec -i -t myname /bin/bash 63 | 64 | 65 | ### Bind mount and/or Docker volume 66 | 67 | In both the reverse proxy setup and the standalone version, the 68 | `/codescene` directory is bound to the 69 | [`docker-codescene/codescene`](docker-codescene/codescene) directory 70 | in this repository. It contains two directories, `repos` and 71 | `analyses` that can be used to store Git repositories and the analysis 72 | result files that CodeScene produces. CodeScene's internal database is 73 | also stored in `/codescene`, as well as a logfile. By using these directories, your data 74 | will be persisted beyond the life of the Docker container. 75 | 76 | Both the standalone command presented above and the `docker-compose` configuration use the `bind` mount type, for 77 | ease of demonstration and debugging. In a production setting, [Docker 78 | volumes](https://docs.docker.com/storage/volumes) would be a better 79 | solution. 80 | 81 | The configuration presented here uses CodeScene's optional environment 82 | variables `CODESCENE_ANALYSIS_RESULTS_ROOT` and 83 | `CODESCENE_CLONED_REPOSITORIES_ROOT`. Their purpose is to ensure that users cannot create 84 | repositories or store analysis results outside of the `/codescene` 85 | directory. In conjunction with the `CODESCENE_DB_PATH`, we can be sure 86 | that all the necessary data for persisting CodeScene is in a single, 87 | easy-to-manage location. You can of course adjust these variables to 88 | fit your specific needs. 89 | 90 | Whether you use volumes or bind mounts, they must be passed to the 91 | Docker container at run time. 92 | 93 | In the full reverse proxy setup using `docker-compose`, this is done 94 | in the `volumes` stanza of the configuration. The 95 | [`docker-compose.yml`](docker-compose.yml) file in this repository 96 | uses a Docker volume. To use a bind mount with `docker-compose`, or 97 | for more detailed instructions, please refer to the documentation 98 | [here](https://docs.docker.com/compose/compose-file/#volumes). 99 | 100 | For the standalone configuration using a bind mount, see [Run 101 | CodeScene by itself without the reverse 102 | proxy](#run-codescene-by-itself-without-the-reverse-proxy). To use a 103 | Docker volume in the standalone configuration, you must first [create 104 | a volume](https://docs.docker.com/storage/volumes/#create-and-manage-volumes): 105 | 106 | docker volume create codescene-volume 107 | 108 | This volume can then be referenced when starting the Docker container: 109 | 110 | docker run -i -t -p 3003 \ 111 | --name myname \ 112 | --mount type=volume,source=codescene-volume,target=/codescene \ 113 | empear/ubuntu-onprem 114 | 115 | Please refer to the [Docker documentation](https://docs.docker.com/storage/volumes) 116 | for instructions on managing your Docker volumes. 117 | 118 | 119 | ### Authentication for remote Git repositories 120 | 121 | To analyze code located on remote servers, CodeScene needs to be able 122 | to clone it with Git. For public repositories, cloning via `https` is 123 | sufficient. Private repositories will require authentication 124 | credentials, for which SSH keys are the recommended form. (For 125 | example, including user credentials in Git URLs is inherently insecure 126 | for requests of an open network.) 127 | 128 | However, it can be tricky to communicate SSH credentials to a Docker 129 | container in a way that allows CodeScene to run unattended. Here are 130 | some options. 131 | 132 | #### Keys without a passphrase 133 | 134 | If you are comfortable using SSH keys that do not require a 135 | passphrase, the simplest solution is to bind a valid `.ssh` directory 136 | on the host system to `/root/.ssh` inside the container. 137 | 138 | With the standalone setup, this would mean supplying an additional 139 | `--mount` argument to `docker run`, something like: 140 | 141 | ``` 142 | --mount type=bind,source=$HOME/codescene-git-keys,destination=/root/.ssh 143 | ``` 144 | 145 | With the `docker-compose` solution, you would add the following to the 146 | `volumes` section of the `codescene` stanza: 147 | 148 | ``` 149 | -"${HOME}/codescene-git-keys:/root/.ssh" 150 | ``` 151 | 152 | The directory at `$HOME/codescene-git-keys` could be tested outside of 153 | Docker to be sure that the SSH connection works correctly. Make sure 154 | that `known_hosts` contains a reference to the servers you will be 155 | cloning from. 156 | 157 | #### GitHub deploy keys 158 | 159 | For greater security, if your remote code is on GitHub, the solution 160 | above could be combined with GitHub's [deploy keys](https://developer.github.com/v3/guides/managing-deploy-keys/#deploy-keys). 161 | 162 | #### Linux host: ssh-agent forwarding 163 | 164 | When running on a Linux host, it may be possible to forward the host 165 | machine's `ssh-agent` to the Docker container by mounting a volume 166 | corresponding to $SSH_AUTH_SOCK (untested): 167 | 168 | ``` 169 | --mount type=bind,source=$(dirname $SSH_AUTH_SOCK),destination=$(dirname $SSH_AUTH_SOCK) \ 170 | -e SSH_AUTH_SOCK=$SSH_AUTH_SOCK 171 | ``` 172 | 173 | #### Dedicated ssh-agent containers 174 | 175 | You may be able to use a dedicated Docker container to store SSH credentials. See: 176 | 177 | - [uber-common/docker-ssh-forward](https://github.com/uber-common/docker-ssh-agent-forward) 178 | - [nadeas/ssh-agent](https://github.com/nardeas/ssh-agent) 179 | 180 | ### Path prefix 181 | 182 | In some situations, it may be necessary to run CodeScene under a path 183 | rather than at the root, eg. `example.com/codescene` rather than 184 | simply `example.com`. 185 | 186 | To do this, you can use the `CODESCENE_PATH_PREFIX` by setting it in 187 | the [Dockerfile](docker-codescene/Dockerfile). The prefix you add 188 | there will be appended to all internal links in CodeScene. 189 | 190 | If you were to use this solution in conjunction with nginx, your [nginx.conf](docker-nginx/nginx.conf) file might include something like this: 191 | 192 | ``` 193 | location /codescene { 194 | return 302 /codescene/; 195 | } 196 | 197 | location /codescene/ { 198 | proxy_pass http://codescene:3003/; 199 | proxy_redirect http:// $scheme://$http_host/codescene; 200 | } 201 | ``` 202 | 203 | 204 | 205 | ### Memory settings 206 | 207 | To adjust memory settings for CodeScene running inside a container, 208 | you can set the `JAVA_OPTIONS` environment variable. 209 | 210 | To set "max heap" explicitly use `-Xmx`: 211 | 212 | ``` 213 | # with explicit max memory => notice that -m 500M is ignored 214 | docker run -p3103:3003 -m 500M -e JAVA_OPTIONS='-Xmx300m' --name codescene empear/ubuntu-onprem 215 | VM settings: 216 | Max. Heap Size: 300.00M 217 | Ergonomics Machine Class: server 218 | Using VM: OpenJDK 64-Bit Server VM 219 | ``` 220 | 221 | To let the JVM autodetect default settings based on the container's memory: 222 | 223 | ``` 224 | # with experimental options and autodetection 225 | # note that -XX:+UseCGroupMemoryLimitForHeap has been deprecated 226 | docker run -p3103:3003 -m 500M -e \ 227 | JAVA_OPTIONS='-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=2' \ 228 | --mount type=bind,source=$PWD/docker-codescene/codescene,destination=/codescene \ 229 | --name codescene empear/ubuntu-onprem 230 | VM settings: 231 | Max. Heap Size (Estimated): 222.50M 232 | Ergonomics Machine Class: server 233 | Using VM: OpenJDK 64-Bit Server VM 234 | ``` 235 | 236 | Please note, that 237 | [support for `-XX:+UseCGroupMemoryLimitForHeap` has been deprecated in JDK 10](https://bugs.openjdk.java.net/browse/JDK-8194086) 238 | and is no longer needed. 239 | 240 | For more details, see 241 | [Java inside docker: What you must know to not FAIL](https://developers.redhat.com/blog/2017/03/14/java-inside-docker/). 242 | 243 | 244 | ### Timezones 245 | 246 | CodeScene, in general, uses default system's timezone. 247 | In our docker image we set the default timezone explicitly to UTC via [`CODESCENE_TIMEZONE` env var](https://github.com/empear-analytics/docker-codescene-nginx-self-signed-ssl/blob/master/docker-codescene/Dockerfile#L30). 248 | This can be overriden when the docker image is run: 249 | ``` 250 | docker run -p3003 -e CODESCENE_TIMEZONE='Europe/Stockholm' empear/ubuntu-onprem 251 | ``` 252 | Note that if you use docker-compose you need to leave out quotes: 253 | ``` 254 | environment: 255 | - CODESCENE_TIMEZONE=Europe/Stockholm 256 | ``` 257 | 258 | ### Use 259 | 260 | Browse to https://localhost. In order to use CodeScene, you will need a 261 | license. You can get a license on the [Empear Customer Portal](https://portal.empear.com/). 262 | For more information about CodeScene, see the [CodeScene Documentation](https://docs.enterprise.codescene.io/). 263 | 264 | ### Stop 265 | 266 | To stop the reverse proxy: 267 | 268 | docker-compose down 269 | 270 | 271 | ### License, Liability & Support 272 | 273 | * The contents of this repository are provided under the [MIT License](https://github.com/empear-analytics/docker-codescene-nginx-self-signed-ssl/blob/master/LICENSE.md). Other licences may apply to the software contained in the Docker images referenced here. 274 | 275 | 276 | ### Analyze this this project on CodeScene 277 | 278 | [![](https://codescene.io/projects/2554/status.svg) Get more details at **codescene.io**.](https://codescene.io/projects/2554/jobs/latest-successful/results) 279 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.2' 2 | 3 | services: 4 | reverseproxy: 5 | build: docker-nginx 6 | ports: 7 | - 443:443 8 | restart: always 9 | 10 | codescene: 11 | depends_on: 12 | - reverseproxy 13 | image: empear/codescene:latest 14 | restart: always 15 | volumes: 16 | - "./docker-codescene/codescene:/codescene" 17 | # environment: 18 | # raise codescene log level for troubleshooting 19 | # - CODESCENE_LOG_LEVEL=DEBUG 20 | # provide custom java options, e.g. proxy settings for project management integration 21 | # - JAVA_OPTIONS=-Dhttp.proxyHost=my.proxy.com -Dhttp.proxyPort=3128 -Dhttps.proxyHost=my.proxy.com -Dhttps.proxyPort=3128 22 | -------------------------------------------------------------------------------- /docker-nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.7 2 | 3 | # 4 | # PACKAGES 5 | # 6 | COPY docker-entrypoint.sh /opt/docker-entrypoint.sh 7 | COPY nginx.conf /nginx/ 8 | RUN apk add --no-cache \ 9 | bash \ 10 | nginx \ 11 | shadow \ 12 | openssl && \ 13 | chmod u+rx,g+rx,o+rx,a-w /opt/docker-entrypoint.sh && \ 14 | usermod -u 10777 nginx && \ 15 | groupmod -g 10777 nginx && \ 16 | mkdir -p /opt/www && \ 17 | mkdir -p /opt/ssl && \ 18 | chown -R nginx:nginx /opt/ && \ 19 | mkdir -p /nginx/tmp/ && \ 20 | chown -R nginx:nginx /nginx/ 21 | 22 | # 23 | # RUN NGINX 24 | # 25 | EXPOSE 443 26 | VOLUME ["/opt/www"] 27 | WORKDIR /opt/www/ 28 | ENTRYPOINT ["/opt/docker-entrypoint.sh"] 29 | CMD ["nginx", "-c", "/nginx/nginx.conf", "-g", "daemon off;"] 30 | -------------------------------------------------------------------------------- /docker-nginx/LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Empear AB 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /docker-nginx/README.md: -------------------------------------------------------------------------------- 1 | # docker-codescene-nginx-self-signed-ssl 2 | 3 | Docker-Image to run nginx as a proxy with a self-signed SSL certificate. 4 | -------------------------------------------------------------------------------- /docker-nginx/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | echo ">> DOCKER-ENTRYPOINT: GENERATING SSL CERT" 6 | 7 | cd /opt/ssl/ 8 | openssl genrsa -des3 -passout pass:x -out server.pass.key 2048 9 | openssl rsa -passin pass:x -in server.pass.key -out server.key 10 | rm server.pass.key 11 | openssl req -new -key server.key -out server.csr -subj "/C=SE/ST=Skane/L=Malmo/O=codescene.io/OU=codescene.io/CN=local.codescene.io" 12 | openssl x509 -req -sha256 -days 300065 -in server.csr -signkey server.key -out server.crt 13 | cd /opt/www/ 14 | 15 | echo ">> DOCKER-ENTRYPOINT: GENERATING SSL CERT ... DONE" 16 | echo ">> DOCKER-ENTRYPOINT: EXECUTING CMD" 17 | 18 | exec "$@" 19 | -------------------------------------------------------------------------------- /docker-nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | error_log /nginx/tmp/error.log; 2 | 3 | pid /nginx/tmp/nginx.pid; 4 | 5 | worker_processes 1; 6 | 7 | events { 8 | worker_connections 1024; 9 | } 10 | 11 | http { 12 | client_body_temp_path /nginx/tmp/client_body; 13 | fastcgi_temp_path /nginx/tmp/fastcgi_temp; 14 | proxy_temp_path /nginx/tmp/proxy_temp; 15 | scgi_temp_path /nginx/tmp/scgi_temp; 16 | uwsgi_temp_path /nginx/tmp/uwsgi_temp; 17 | 18 | sendfile off; 19 | 20 | tcp_nopush on; 21 | tcp_nodelay on; 22 | # increase read timeout to avoid 504 when cloning larger repos on the "New Project" page 23 | proxy_read_timeout 600; 24 | keepalive_timeout 65; 25 | types_hash_max_size 2048; 26 | 27 | include /etc/nginx/mime.types; 28 | index index.html index.htm index.php; 29 | 30 | log_format main '$remote_addr - $remote_user [$time_local] $status ' 31 | '"$request" $body_bytes_sent "$http_referer" ' 32 | '"$http_user_agent" "$http_x_forwarded_for"'; 33 | 34 | default_type application/octet-stream; 35 | 36 | server { 37 | listen 443; 38 | ssl on; 39 | ssl_certificate /opt/ssl/server.crt; 40 | ssl_certificate_key /opt/ssl/server.key; 41 | ssl_session_cache shared:SSL:10m; 42 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 43 | ssl_prefer_server_ciphers on; 44 | server_name local.codescene.io; 45 | index index.html index.htm; 46 | root /opt/www; 47 | access_log /nginx/tmp/access.log; 48 | error_log /nginx/tmp/error.log; 49 | 50 | location / { 51 | # upstream hostname is service name in docker-compose.yml 52 | proxy_pass http://codescene:3003; 53 | 54 | proxy_redirect http:// $scheme://; 55 | proxy_set_header Host $http_host; 56 | proxy_set_header X-Real-IP $remote_addr; 57 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 58 | proxy_set_header X-Forwarded-Proto $scheme; 59 | } 60 | } 61 | } 62 | --------------------------------------------------------------------------------