├── .browserslistrc ├── .dockerignore ├── .editorconfig ├── .github ├── dependabot.yml └── workflows │ └── pull-request.yml ├── .gitignore ├── Dockerfile ├── README.md ├── angular.json ├── docker-compose.yml ├── karma.conf.js ├── nginx.conf ├── package-lock.json ├── package.json ├── src ├── app │ ├── app.component.css │ ├── app.component.html │ ├── app.component.spec.ts │ ├── app.component.ts │ └── app.module.ts ├── assets │ └── .gitkeep ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts ├── styles.css ├── test.ts ├── tsconfig.app.json ├── tsconfig.spec.json └── typings.d.ts └── tsconfig.json /.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | e2e 2 | node_modules 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: monthly 7 | open-pull-requests-limit: 10 8 | -------------------------------------------------------------------------------- /.github/workflows/pull-request.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v3 14 | - name: Setup Node.js 15 | uses: actions/setup-node@v3 16 | with: 17 | node-version: 14 18 | cache: 'npm' 19 | - name: Test 20 | run: | 21 | npm ci 22 | npm run build 23 | npm run test:ci 24 | env: 25 | CI: true 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /dist-server 6 | /tmp 7 | /out-tsc 8 | 9 | # dependencies 10 | /node_modules 11 | 12 | # IDEs and editors 13 | /.idea 14 | .project 15 | .classpath 16 | .c9/ 17 | *.launch 18 | .settings/ 19 | *.sublime-workspace 20 | 21 | # IDE - VSCode 22 | .vscode/* 23 | !.vscode/settings.json 24 | !.vscode/tasks.json 25 | !.vscode/launch.json 26 | !.vscode/extensions.json 27 | 28 | # misc 29 | /.angular/cache 30 | /.sass-cache 31 | /connect.lock 32 | /coverage 33 | /libpeerconnection.log 34 | npm-debug.log 35 | yarn-error.log 36 | testem.log 37 | /typings 38 | 39 | # e2e 40 | /e2e/*.js 41 | /e2e/*.map 42 | 43 | # System Files 44 | .DS_Store 45 | Thumbs.db 46 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Step 1: Build the app in image 'builder' 2 | FROM node:12.8-alpine AS builder 3 | 4 | WORKDIR /usr/src/app 5 | COPY . . 6 | RUN yarn && yarn build 7 | 8 | # Step 2: Use build output from 'builder' 9 | FROM nginx:stable-alpine 10 | LABEL version="1.0" 11 | 12 | COPY nginx.conf /etc/nginx/nginx.conf 13 | 14 | WORKDIR /usr/share/nginx/html 15 | COPY --from=builder /usr/src/app/dist/my-angular-app/ . 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Docker 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli). 4 | 5 | Angular: 15.x 6 | 7 | ## Scripts 8 | 9 | | Script | Description | Example | 10 | | ------------ | -------------------------------------------- | ----------------------------------- | 11 | | start | start the application | `npm start` | 12 | | build | built application for production | `npm run build` | 13 | | build:docker | build docker image | `npm run build:docker` | 14 | | start:docker | start the prebuilt docker image on port 3000 | `npm run start:docker` | 15 | | test | run unit tests in watch mode | `npm test` | 16 | | test:ci | run unit tests for CI/CD environment | `npm run test:ci` | 17 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "cli": { 6 | "packageManager": "npm" 7 | }, 8 | "projects": { 9 | "medium-angular-docker": { 10 | "root": "", 11 | "sourceRoot": "src", 12 | "projectType": "application", 13 | "architect": { 14 | "build": { 15 | "builder": "@angular-devkit/build-angular:browser", 16 | "options": { 17 | "outputPath": "dist/my-angular-app", 18 | "index": "src/index.html", 19 | "main": "src/main.ts", 20 | "tsConfig": "src/tsconfig.app.json", 21 | "polyfills": "src/polyfills.ts", 22 | "assets": [ 23 | "src/assets", 24 | "src/favicon.ico" 25 | ], 26 | "styles": [ 27 | "src/styles.css" 28 | ], 29 | "scripts": [], 30 | "vendorChunk": true, 31 | "extractLicenses": false, 32 | "buildOptimizer": false, 33 | "sourceMap": true, 34 | "optimization": false, 35 | "namedChunks": true 36 | }, 37 | "configurations": { 38 | "production": { 39 | "budgets": [ 40 | { 41 | "type": "anyComponentStyle", 42 | "maximumWarning": "6kb" 43 | } 44 | ], 45 | "optimization": true, 46 | "outputHashing": "all", 47 | "sourceMap": false, 48 | "namedChunks": false, 49 | "extractLicenses": true, 50 | "vendorChunk": false, 51 | "buildOptimizer": true, 52 | "fileReplacements": [ 53 | { 54 | "replace": "src/environments/environment.ts", 55 | "with": "src/environments/environment.prod.ts" 56 | } 57 | ] 58 | } 59 | }, 60 | "defaultConfiguration": "" 61 | }, 62 | "serve": { 63 | "builder": "@angular-devkit/build-angular:dev-server", 64 | "options": { 65 | "browserTarget": "medium-angular-docker:build" 66 | }, 67 | "configurations": { 68 | "production": { 69 | "browserTarget": "medium-angular-docker:build:production" 70 | } 71 | } 72 | }, 73 | "test": { 74 | "builder": "@angular-devkit/build-angular:karma", 75 | "options": { 76 | "main": "src/test.ts", 77 | "karmaConfig": "./karma.conf.js", 78 | "polyfills": "src/polyfills.ts", 79 | "tsConfig": "src/tsconfig.spec.json", 80 | "scripts": [], 81 | "styles": [ 82 | "src/styles.css" 83 | ], 84 | "assets": [ 85 | "src/assets", 86 | "src/favicon.ico" 87 | ] 88 | } 89 | } 90 | } 91 | } 92 | }, 93 | "schematics": { 94 | "@schematics/angular:component": { 95 | "prefix": "app", 96 | "style": "css" 97 | }, 98 | "@schematics/angular:directive": { 99 | "prefix": "app" 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | 3 | services: 4 | app: 5 | image: 'my-angular-app' 6 | build: '.' 7 | ports: 8 | - 3000:80 9 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ], 20 | fixWebpackSourcePaths: true 21 | }, 22 | 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: true, 30 | customLaunchers: { 31 | ChromeHeadless: { 32 | base: 'Chrome', 33 | flags: [ 34 | '--headless', 35 | '--disable-gpu', 36 | // Without a remote debugging port, Google Chrome exits immediately. 37 | '--remote-debugging-port=9222' 38 | ] 39 | } 40 | } 41 | }); 42 | }; 43 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes 1; 2 | 3 | events { 4 | worker_connections 1024; 5 | } 6 | 7 | http { 8 | server { 9 | listen 80; 10 | server_name localhost; 11 | 12 | root /usr/share/nginx/html; 13 | index index.html index.htm; 14 | include /etc/nginx/mime.types; 15 | 16 | gzip on; 17 | gzip_min_length 1000; 18 | gzip_proxied expired no-cache no-store private auth; 19 | gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; 20 | 21 | location / { 22 | try_files $uri $uri/ /index.html; 23 | } 24 | 25 | location ~ \.html$ { 26 | add_header Cache-Control "private, no-cache, no-store, must-revalidate"; 27 | add_header Expires "Sat, 01 Jan 2000 00:00:00 GMT"; 28 | add_header Pragma no-cache; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-docker", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "ng", 7 | "start": "ng serve --open", 8 | "build": "ng build --configuration production", 9 | "build:docker": "docker image build -t my-angular-app .", 10 | "start:docker": "docker run -p 3000:80 --rm my-angular-app", 11 | "test": "ng test --browsers=ChromeHeadless", 12 | "test:ci": "ng test --watch=false --browsers=ChromeHeadless" 13 | }, 14 | "private": true, 15 | "dependencies": { 16 | "@angular/animations": "15.2.1", 17 | "@angular/common": "15.2.1", 18 | "@angular/compiler": "15.2.1", 19 | "@angular/core": "15.2.1", 20 | "@angular/forms": "15.2.1", 21 | "@angular/platform-browser": "15.2.1", 22 | "@angular/platform-browser-dynamic": "15.2.1", 23 | "@angular/router": "15.2.1", 24 | "rxjs": "^7.8.0", 25 | "tslib": "^2.5.0", 26 | "zone.js": "^0.12.0" 27 | }, 28 | "devDependencies": { 29 | "@angular-devkit/build-angular": "^15.2.1", 30 | "@angular/cli": "15.2.1", 31 | "@angular/compiler-cli": "15.2.1", 32 | "@angular/language-service": "15.2.1", 33 | "@types/jasmine": "^4.3.1", 34 | "@types/jasminewd2": "~2.0.10", 35 | "@types/node": "^18.14.6", 36 | "jasmine-core": "^4.5.0", 37 | "karma": "^6.4.1", 38 | "karma-chrome-launcher": "~3.1.1", 39 | "karma-coverage-istanbul-reporter": "~3.0.2", 40 | "karma-jasmine": "^5.1.0", 41 | "karma-jasmine-html-reporter": "^2.0.0", 42 | "typescript": "4.9.5" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenysVuika/medium-angular-docker/74963eddc729531951a074c65910cf038607a556/src/app/app.component.css -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

4 | Welcome to Dockerized {{ title }}! 5 |

6 | Angular Logo 7 |
8 |

Here are some links to help you start:

9 | 20 | 21 | -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, waitForAsync } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | describe('AppComponent', () => { 4 | beforeEach(waitForAsync(() => { 5 | TestBed.configureTestingModule({ 6 | declarations: [ 7 | AppComponent 8 | ], 9 | }).compileComponents(); 10 | })); 11 | it('should create the app', waitForAsync(() => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.debugElement.componentInstance; 14 | expect(app).toBeTruthy(); 15 | })); 16 | it(`should have as title 'app'`, waitForAsync(() => { 17 | const fixture = TestBed.createComponent(AppComponent); 18 | const app = fixture.debugElement.componentInstance; 19 | expect(app.title).toEqual('app'); 20 | })); 21 | it('should render title in a h1 tag', waitForAsync(() => { 22 | const fixture = TestBed.createComponent(AppComponent); 23 | fixture.detectChanges(); 24 | const compiled = fixture.debugElement.nativeElement; 25 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to Dockerized app!'); 26 | })); 27 | }); 28 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'] 7 | }) 8 | export class AppComponent { 9 | title = 'app'; 10 | } 11 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | 4 | 5 | import { AppComponent } from './app.component'; 6 | 7 | 8 | @NgModule({ 9 | declarations: [ 10 | AppComponent 11 | ], 12 | imports: [ 13 | BrowserModule 14 | ], 15 | providers: [], 16 | bootstrap: [AppComponent] 17 | }) 18 | export class AppModule { } 19 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenysVuika/medium-angular-docker/74963eddc729531951a074c65910cf038607a556/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false 8 | }; 9 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenysVuika/medium-angular-docker/74963eddc729531951a074c65910cf038607a556/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular Docker 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.log(err)); 13 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /** 5 | * By default, zone.js will patch all possible macroTask and DomEvents 6 | * user can disable parts of macroTask/DomEvents patch by setting following flags 7 | */ 8 | 9 | // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 10 | // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 11 | // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 12 | 13 | /* 14 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 15 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 16 | */ 17 | // (window as any).__Zone_enable_cross_context_check = true; 18 | 19 | /*************************************************************************************************** 20 | * Zone JS is required by default for Angular itself. 21 | */ 22 | import 'zone.js'; // Included with Angular CLI. 23 | 24 | 25 | 26 | /*************************************************************************************************** 27 | * APPLICATION IMPORTS 28 | */ 29 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | // First, initialize the Angular testing environment. 11 | getTestBed().initTestEnvironment( 12 | BrowserDynamicTestingModule, 13 | platformBrowserDynamicTesting(), { 14 | teardown: { destroyAfterEach: false } 15 | } 16 | ); 17 | -------------------------------------------------------------------------------- /src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "baseUrl": "./", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "main.ts", 10 | "polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "baseUrl": "./", 6 | "types": [ 7 | "jasmine", 8 | "node" 9 | ] 10 | }, 11 | "files": [ 12 | "test.ts", 13 | "polyfills.ts" 14 | ], 15 | "include": [ 16 | "**/*.spec.ts", 17 | "**/*.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare var module: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "downlevelIteration": true, 5 | "importHelpers": true, 6 | "outDir": "./dist/out-tsc", 7 | "sourceMap": true, 8 | "declaration": false, 9 | "moduleResolution": "node", 10 | "experimentalDecorators": true, 11 | "target": "ES2022", 12 | "typeRoots": [ 13 | "node_modules/@types" 14 | ], 15 | "lib": [ 16 | "es2017", 17 | "dom" 18 | ], 19 | "module": "es2020", 20 | "baseUrl": "./", 21 | "useDefineForClassFields": false 22 | } 23 | } --------------------------------------------------------------------------------