Docker copy images between hosts

Copying docker images (import/export) between hosts

Sometimes it's useful to export a local docker image to another host without going through a repository

docker save -o [path for generated tar file] [image name]

For example :

docker save -o mycool-container.tar ufasoli/mycool-container:1.0

You will then need to copy the saved .tar image to the target host by however mean suits you (FTP, USB, SCP)

Once the image copied to the target host import the image to the local docker

docker load -i [path to image tar file]

Like so :

docker load -i mycool-container.tar

Depending on the size of the image this can be a long operation, but once it's finished you should be able to see your image with the usual docker images command

docker compose on multiple environments

docker-compose is a pretty cool tool that allows you to bootstrap and run multiple docker containers with 1 configuration file

Below is an example docker-compose file for staring a 3 node confluent kafka cluster

---
version: '2'
services:
  zookeeper:
    image: confluentinc/cp-zookeeper:latest
    network_mode: host
    environment:
      ZOOKEEPER_CLIENT_PORT: 32181
      ZOOKEEPER_TICK_TIME: 2000
    extra_hosts:
      - "moby:127.0.0.1"
    restart: always

  kafka-1:
    image: confluentinc/cp-kafka:latest
    network_mode: host
    depends_on:
      - zookeeper
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: localhost:32181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://myserver.com:29092
    restart: always
    extra_hosts:
      - "moby:127.0.0.1"

  kafka-2:
      image: confluentinc/cp-kafka:latest
      network_mode: host
      depends_on:
        - zookeeper
      environment:
        KAFKA_BROKER_ID: 2
        KAFKA_ZOOKEEPER_CONNECT: localhost:32181
        KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://myserver.com:29093
      restart: always
      extra_hosts:
        - "moby:127.0.0.1"

  kafka-3:
        image: confluentinc/cp-kafka:latest
        network_mode: host
        depends_on:
          - zookeeper
        environment:
          KAFKA_BROKER_ID: 3
          KAFKA_ZOOKEEPER_CONNECT: localhost:32181
          KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://myserver.com:29094
        restart: always
        extra_hosts:
          - "moby:127.0.0.1"

  kafka-rest:
    image: confluentinc/cp-kafka-rest:latest
    network_mode: host
    depends_on:
      - kafka-1
      - kafka-2
      - kafka-3
    restart: always
    environment:
      KAFKA_REST_ZOOKEEPER_CONNECT: localhost:32181
      KAFKA_REST_LISTENERS: http://0.0.0.0:8082
      KAFKA_REST_HOST_NAME: kafka-rest
    extra_hosts:
      - "moby:127.0.0.1"

---
version: '2'
services:
  zookeeper:
    image: confluentinc/cp-zookeeper:latest
    network_mode: host
    environment:
      ZOOKEEPER_CLIENT_PORT: 32181
      ZOOKEEPER_TICK_TIME: 2000
    extra_hosts:
      - "moby:127.0.0.1"
    restart: always

  kafka-1:
    image: confluentinc/cp-kafka:latest
    network_mode: host
    depends_on:
      - zookeeper
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: localhost:32181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://test.myserver.com:29092
    restart: always
    extra_hosts:
      - "moby:127.0.0.1"

  kafka-2:
      image: confluentinc/cp-kafka:latest
      network_mode: host
      depends_on:
        - zookeeper
      environment:
        KAFKA_BROKER_ID: 2
        KAFKA_ZOOKEEPER_CONNECT: localhost:32181
        KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://test.myserver.com:29093
      restart: always
      extra_hosts:
        - "moby:127.0.0.1"

  kafka-3:
        image: confluentinc/cp-kafka:latest
        network_mode: host
        depends_on:
          - zookeeper
        environment:
          KAFKA_BROKER_ID: 3
          KAFKA_ZOOKEEPER_CONNECT: localhost:32181
          KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://test.myserver.com:29094
        restart: always
        extra_hosts:
          - "moby:127.0.0.1"

  kafka-rest:
    image: confluentinc/cp-kafka-rest:latest
    network_mode: host
    depends_on:
      - kafka-1
      - kafka-2
      - kafka-3
    restart: always
    environment:
      KAFKA_REST_ZOOKEEPER_CONNECT: localhost:32181
      KAFKA_REST_LISTENERS: http://0.0.0.0:8082
      KAFKA_REST_HOST_NAME: kafka-rest
    extra_hosts:
      - "moby:127.0.0.1"

You can now run docker-compose by with a second -f and the redefined properties in the test file will ovewrite those in the base file

docker-compose -f docker-compose.yml -f docker-compose.test.yml up -d

More information regarding docker compose advanced configuration can be found here

Angular6 hiding component selector

It's sometimes useful to have angular's component selector not to be rendered in the page, as sometimes this can cause problems with CSS rendering (since we will have an intermediate tag in between 2 tags)

For example :


@Component({
    selector: 'my-component'
})
export class MyComponent{

@Input()
title:String;


}
...

Now you will use your component for example like so :


<html>
.....

<div class='container'>
<my-component [title]="'Test'" ></my-component>

</div>
.....

</html>

With this approach in the rendered HTML you will have the angular component tab generated inside the div but what if this causes problems with some CSS code ?

Well luckily enough there's a simple way to change this and that is changer your selector from a tag to an attribute


@Component({
    selector: '[my-component]'
})
export class MyComponent{

@Input()
title:String;


}
...

By changing the value of the selector property from my-component to [my-component] you should be able to "apply" your component directly to a standard HTML tag, so this will prevent the <my-component> tag to be rendered in the final HTML


<html>
.....
<div class='container' [title]="'Test'" my-component >


</div>
.....

</html>

OSX paste unformatted text / remove text formatting

So recently I found about what is for me one of the best keyboard shortcuts on OSX often I copy text from somewhere and whenever I paste it it comes with all the original formatting, which TBH mostly of the time is a pain (at least for me) even though a lot of applications have a "paste special" or something like that is a bit cumbersome to me

So the following keyboard shortcut allows you to paste unformatted text in almost any application :

This for me is a great productivity shortcut and one of the best ones I found for OSX

Angular 4/5 override class in body tag (Shadow Piercing combinators approach)

In angular component CSS styles are encapsulated into the component's view and don't affect the rest of the application; usually this is the behaviour that you want however sometimes it's useful to be able to affect tags outside the component, for example the body tag

This can be achieved in a few different ways, like for example tweaking view encapsulation parameters

In this post I will show you a CSS approach to this using The Shadow Piercing combinators, starting in Angular 4.3.0 you can use the custom shadow piercing combinator ::ng-deep to achieve this

For example if we had a component named "CustomComponent" we could have a set of files similar to :

  • custom.component.ts
  • custom.component.css
  • custom.component.html

In order for us to shadow and override the main body tag would be to put the following in the custom.component.css :

::ng-deep body {
  min-height: 75rem;
  padding-top: 4.5rem;
}

BigDecimal rounding to the nearest 5 cents with Java's BigDecimal

Recently I hat to implement a function that would round to the nearest 5 cents and after googling around a bit I found bits and pieces here and there but none just worked for me, so below you can find a function that should do just that

/**
     * Rounds a decimal number to the nearest 5 cents using the following rules
     * 
     * Rounding rules :
     * - 0.1299 = 0.10
     * - 0.1300 = 0.15
     * - 0.1799 = 0.15
     * - 0.1800 = 0.20
     *
     * @param value the BigDecimal value to round
     * @return the rounded value for the big decimal with a scale of 2
     */
    public static BigDecimal roundToNearest5Cents(final BigDecimal value) {
        return value.setScale(2, RoundingMode.FLOOR).multiply(new BigDecimal(20)).add(new BigDecimal("0.5"))
                .setScale(0, RoundingMode.FLOOR).divide(new BigDecimal(20)).setScale(2, RoundingMode.FLOOR);
    }

Spring application events lifecycle and earlyApplicationEvents

Not long ago I learned the hard way the way spring handles earlyApplication events when we started having problems in one of our projects

Basically we were using a MongoDB database as a cache layer, so when the application would startup we would pull most of the data from our RDBMS do some processing and denormalisation then fill the MongoDB with data

The application had been running mostly fine for some time but we saw some memory issues as the data kept growing within the application and I suspected a Memory leak issue

So I decided to do a java heap dump to try to see what was happening, and I found the culprit; way down the piping of spring the org.springframework.context.support.AbstractApplicationContext class had a private property earlyApplicationEvents that was keeping references to more than 3 million instances of BasicDBObject that were not Garbage collected even though they were no longer in scope and were already written to the database

After scouring the internet a fellow developer pointed out to me that the property : earlyApplicationEvents is :

basically holds onto events during startup until the listeners can be registered, at which point it will get set to null

So with this information I could simple push my heavy duty task later on the spring application events lifecycle by using spring's handy application events mechanism.

For those who don't know what application events are; application events are available since the very beginning of the Spring framework as a mean for loosely coupled components to exchange information; the main application events are :

  1. ContextRefreshedEvent : published when the ApplicationContext is either initialized or refreshed
  2. ContextStartedEvent : when the ApplicationContext is started using the start() method on the ConfigurableApplicationContext interface. You can poll your database or you can restart any stopped application after receiving this event
  3. ContextStoppedEvent : published when the ApplicationContext is stopped using the stop() method on the ConfigurableApplicationContext interface. You can do required housekeep work after receiving this event.
  4. ContextClosedEvent : published when the ApplicationContext is closed using the close() method on the ConfigurableApplicationContext interface. A closed context reaches its end of life; it cannot be refreshed or restarted.

in my case after the context has been refreshed like so :


@Configuration
public class MyConfigClass implements ApplicationListener<ContextRefreshedEvent>{


    //Misc code
    
    private final InitializationService initializationService;

    
    @Autowired
    public MyConfigClass(InitializationService initializationService){
       this. initializationService = initializationService;
    }

 @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        initializationService.init();
    }
}

So if I can leave you with a parting "word of wisdom" : Be careful WHEN you are running certain operations in respect to the Spring Application events lifecycle and the possible side-effects that this can cause

for more info on application events please read the spring official documentation

Docker copy images between hosts

Copying docker images (import/export) between hosts Sometimes it's useful to export a local docker image to another host without going...